diff -NurpP --minimal linux-2.6.22.19/Documentation/vserver/debug.txt linux-2.6.22.19-g-v/Documentation/vserver/debug.txt --- linux-2.6.22.19/Documentation/vserver/debug.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22.19-g-v/Documentation/vserver/debug.txt 2008-03-04 08:55:58.000000000 +0100 @@ -0,0 +1,154 @@ + +debug_cvirt: + + 2 4 "vx_map_tgid: %p/%llx: %d -> %d" + "vx_rmap_tgid: %p/%llx: %d -> %d" + +debug_dlim: + + 0 1 "ALLOC (%p,#%d)%c inode (%d)" + "FREE (%p,#%d)%c inode" + 1 2 "ALLOC (%p,#%d)%c %lld bytes (%d)" + "FREE (%p,#%d)%c %lld bytes" + 2 4 "ADJUST: %lld,%lld on %ld,%ld [mult=%d]" + 3 8 "ext3_has_free_blocks(%p): %lu<%lu+1, %c, %u!=%u r=%d" + "ext3_has_free_blocks(%p): free=%lu, root=%lu" + "rcu_free_dl_info(%p)" + 4 10 "alloc_dl_info(%p,%d) = %p" + "dealloc_dl_info(%p)" + "get_dl_info(%p[#%d.%d])" + "put_dl_info(%p[#%d.%d])" + 5 20 "alloc_dl_info(%p,%d)*" + 6 40 "__hash_dl_info: %p[#%d]" + "__unhash_dl_info: %p[#%d]" + 7 80 "locate_dl_info(%p,#%d) = %p" + +debug_misc: + + 0 1 "destroy_dqhash: %p [#0x%08x] c=%d" + "new_dqhash: %p [#0x%08x]" + "vroot[%d]_clr_dev: dev=%p[%lu,%d:%d]" + "vroot[%d]_get_real_bdev: dev=%p[%lu,%d:%d]" + "vroot[%d]_set_dev: dev=%p[%lu,%d:%d]" + "vroot_get_real_bdev not set" + 1 2 "cow_break_link(»%s«)" + "temp copy »%s«" + 2 4 "dentry_open(new): %p" + "dentry_open(old): %p" + "lookup_create(new): %p" + "old path »%s«" + "path_lookup(old): %d" + "vfs_create(new): %d" + "vfs_rename: %d" + "vfs_sendfile: %d" + 3 8 "fput(new_file=%p[#%d])" + "fput(old_file=%p[#%d])" + 4 10 "vx_info_kill(%p[#%d],%d,%d) = %d" + "vx_info_kill(%p[#%d],%d,%d)*" + 5 20 "vs_reboot(%p[#%d],%d)" + 6 40 "dropping task %p[#%u,%u] for %p[#%u,%u]" + +debug_net: + + 2 4 "nx_addr_conflict(%p,%p) %d.%d,%d.%d" + 3 8 "inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d" + "inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d" + 4 10 "ip_route_connect(%p) %p,%p;%lx" + 5 20 "__addr_in_socket(%p,%d.%d.%d.%d) %p:%d.%d.%d.%d %p;%lx" + 6 40 "sk,egf: %p [#%d] (from %d)" + "sk,egn: %p [#%d] (from %d)" + "sk,req: %p [#%d] (from %d)" + "sk: %p [#%d] (from %d)" + "tw: %p [#%d] (from %d)" + 7 80 "__sock_recvmsg: %p[%p,%p,%p;%d]:%d/%d" + "__sock_sendmsg: %p[%p,%p,%p;%d]:%d/%d" + +debug_nid: + + 0 1 "__lookup_nx_info(#%u): %p[#%u]" + "alloc_nx_info(%d) = %p" + "create_nx_info(%d) (dynamic rejected)" + "create_nx_info(%d) = %p (already there)" + "create_nx_info(%d) = %p (new)" + "dealloc_nx_info(%p)" + 1 2 "alloc_nx_info(%d)*" + "create_nx_info(%d)*" + 2 4 "get_nx_info(%p[#%d.%d])" + "put_nx_info(%p[#%d.%d])" + 3 8 "claim_nx_info(%p[#%d.%d.%d]) %p" + "clr_nx_info(%p[#%d.%d])" + "init_nx_info(%p[#%d.%d])" + "release_nx_info(%p[#%d.%d.%d]) %p" + "set_nx_info(%p[#%d.%d])" + 4 10 "__hash_nx_info: %p[#%d]" + "__nx_dynamic_id: [#%d]" + "__unhash_nx_info: %p[#%d.%d.%d]" + 5 20 "moved task %p into nxi:%p[#%d]" + "nx_migrate_task(%p,%p[#%d.%d.%d])" + "task_get_nx_info(%p)" + 6 40 "nx_clear_persistent(%p[#%d])" + +debug_quota: + + 0 1 "quota_sync_dqh(%p,%d) discard inode %p" + 1 2 "quota_sync_dqh(%p,%d)" + "sync_dquots(%p,%d)" + "sync_dquots_dqh(%p,%d)" + 3 8 "do_quotactl(%p,%d,cmd=%d,id=%d,%p)" + +debug_switch: + + 0 1 "vc: VCMD_%02d_%d[%d], %d,%p [%d,%d,%x,%x]" + 1 2 "vc: VCMD_%02d_%d[%d] = %08lx(%ld) [%d,%d]" + 4 10 "%s: (%s %s) returned %s with %d" + +debug_tag: + + 7 80 "dx_parse_tag(»%s«): %d:#%d" + "dx_propagate_tag(%p[#%lu.%d]): %d,%d" + +debug_xid: + + 0 1 "__lookup_vx_info(#%u): %p[#%u]" + "alloc_vx_info(%d) = %p" + "alloc_vx_info(%d)*" + "create_vx_info(%d) (dynamic rejected)" + "create_vx_info(%d) = %p (already there)" + "create_vx_info(%d) = %p (new)" + "dealloc_vx_info(%p)" + "loc_vx_info(%d) = %p (found)" + "loc_vx_info(%d) = %p (new)" + "loc_vx_info(%d) = %p (not available)" + 1 2 "create_vx_info(%d)*" + "loc_vx_info(%d)*" + 2 4 "get_vx_info(%p[#%d.%d])" + "put_vx_info(%p[#%d.%d])" + 3 8 "claim_vx_info(%p[#%d.%d.%d]) %p" + "clr_vx_info(%p[#%d.%d])" + "init_vx_info(%p[#%d.%d])" + "release_vx_info(%p[#%d.%d.%d]) %p" + "set_vx_info(%p[#%d.%d])" + 4 10 "__hash_vx_info: %p[#%d]" + "__unhash_vx_info: %p[#%d.%d.%d]" + "__vx_dynamic_id: [#%d]" + 5 20 "enter_vx_info(%p[#%d],%p) %p[#%d,%p]" + "leave_vx_info(%p[#%d,%p]) %p[#%d,%p]" + "moved task %p into vxi:%p[#%d]" + "task_get_vx_info(%p)" + "vx_migrate_task(%p,%p[#%d.%d])" + 6 40 "vx_clear_persistent(%p[#%d])" + "vx_exit_init(%p[#%d],%p[#%d,%d,%d])" + "vx_set_init(%p[#%d],%p[#%d,%d,%d])" + "vx_set_persistent(%p[#%d])" + "vx_set_reaper(%p[#%d],%p[#%d,%d])" + 7 80 "vx_child_reaper(%p[#%u,%u]) = %p[#%u,%u]" + + +debug_limit: + + n 2^n "vx_acc_cres[%5d,%s,%2d]: %5d%s" + "vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d" + + m 2^m "vx_acc_page[%5d,%s,%2d]: %5d%s" + "vx_acc_pages[%5d,%s,%2d]: %5d += %5d" + "vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d" diff -NurpP --minimal linux-2.6.22.19/Makefile linux-2.6.22.19-g-v/Makefile --- linux-2.6.22.19/Makefile 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/Makefile 2008-03-04 08:55:58.000000000 +0100 @@ -312,7 +312,7 @@ LINUXINCLUDE := -Iinclude \ CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) -CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ +CFLAGS := -Wall -W -Wno-unused -Wno-sign-compare -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common AFLAGS := -D__ASSEMBLY__ @@ -553,7 +553,7 @@ export mod_strip_cmd ifeq ($(KBUILD_EXTMOD),) -core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ diff -NurpP --minimal linux-2.6.22.19/arch/alpha/Kconfig linux-2.6.22.19-g-v/arch/alpha/Kconfig --- linux-2.6.22.19/arch/alpha/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -662,6 +662,8 @@ config DUMMY_CONSOLE depends on VGA_HOSE default y +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/asm-offsets.c linux-2.6.22.19-g-v/arch/alpha/kernel/asm-offsets.c --- linux-2.6.22.19/arch/alpha/kernel/asm-offsets.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/asm-offsets.c 2008-03-04 08:55:58.000000000 +0100 @@ -36,6 +36,7 @@ void foo(void) DEFINE(PT_PTRACED, PT_PTRACED); DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + DEFINE(CLONE_KTHREAD, CLONE_KTHREAD); DEFINE(SIGCHLD, SIGCHLD); BLANK(); diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/entry.S linux-2.6.22.19-g-v/arch/alpha/kernel/entry.S --- linux-2.6.22.19/arch/alpha/kernel/entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/entry.S 2008-03-04 08:55:58.000000000 +0100 @@ -643,7 +643,7 @@ kernel_thread: stq $2, 152($sp) /* HAE */ /* Shuffle FLAGS to the front; add CLONE_VM. */ - ldi $1, CLONE_VM|CLONE_UNTRACED + ldi $1, CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD; or $18, $1, $16 bsr $26, sys_clone @@ -872,24 +872,15 @@ sys_getxgid: .globl sys_getxpid .ent sys_getxpid sys_getxpid: + lda $sp, -16($sp) + stq $26, 0($sp) .prologue 0 - ldq $2, TI_TASK($8) - /* See linux/kernel/timer.c sys_getppid for discussion - about this loop. */ - ldq $3, TASK_GROUP_LEADER($2) - ldq $4, TASK_REAL_PARENT($3) - ldl $0, TASK_TGID($2) -1: ldl $1, TASK_TGID($4) -#ifdef CONFIG_SMP - mov $4, $5 - mb - ldq $3, TASK_GROUP_LEADER($2) - ldq $4, TASK_REAL_PARENT($3) - cmpeq $4, $5, $5 - beq $5, 1b -#endif - stq $1, 80($sp) + lda $16, 96($sp) + jsr $26, do_getxpid + ldq $26, 0($sp) + + lda $sp, 16($sp) ret .end sys_getxpid diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/module.c linux-2.6.22.19-g-v/arch/alpha/kernel/module.c --- linux-2.6.22.19/arch/alpha/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/module.c 2008-03-04 08:55:58.000000000 +0100 @@ -177,7 +177,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, /* The small sections were sorted to the end of the segment. The following should definitely cover them. */ - gp = (u64)me->module_core + me->core_size - 0x8000; + gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000; got = sechdrs[me->arch.gotsecindex].sh_addr; for (i = 0; i < n; i++) { diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/osf_sys.c linux-2.6.22.19-g-v/arch/alpha/kernel/osf_sys.c --- linux-2.6.22.19/arch/alpha/kernel/osf_sys.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/osf_sys.c 2008-03-04 08:55:58.000000000 +0100 @@ -883,7 +883,7 @@ osf_gettimeofday(struct timeval32 __user { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } @@ -1288,6 +1288,10 @@ arch_get_unmapped_area(struct file *filp merely specific addresses, but regions of memory -- perhaps this feature should be incorporated into all ports? */ +#ifdef CONFIG_PAX_RANDMMAP + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + if (addr) { addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); if (addr != (unsigned long) -ENOMEM) @@ -1295,8 +1299,8 @@ arch_get_unmapped_area(struct file *filp } /* Next, try allocating at TASK_UNMAPPED_BASE. */ - addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), - len, limit); + addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit); + if (addr != (unsigned long) -ENOMEM) return addr; diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/ptrace.c linux-2.6.22.19-g-v/arch/alpha/kernel/ptrace.c --- linux-2.6.22.19/arch/alpha/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/ptrace.c 2008-03-04 08:55:58.000000000 +0100 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -283,6 +285,16 @@ do_sys_ptrace(long request, long pid, lo goto out_notsk; } + if (gr_handle_ptrace(child, request)) { + ret = -EPERM; + goto out; + } + + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) { + ret = -EPERM; + goto out; + } + if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out; diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/semaphore.c linux-2.6.22.19-g-v/arch/alpha/kernel/semaphore.c --- linux-2.6.22.19/arch/alpha/kernel/semaphore.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/semaphore.c 2008-03-04 08:55:58.000000000 +0100 @@ -68,8 +68,8 @@ __down_failed(struct semaphore *sem) DECLARE_WAITQUEUE(wait, tsk); #ifdef CONFIG_DEBUG_SEMAPHORE - printk("%s(%d): down failed(%p)\n", - tsk->comm, tsk->pid, sem); + printk("%s(%d:#%u): down failed(%p)\n", + tsk->comm, tsk->pid, tsk->xid, sem); #endif tsk->state = TASK_UNINTERRUPTIBLE; @@ -97,8 +97,8 @@ __down_failed(struct semaphore *sem) wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE - printk("%s(%d): down acquired(%p)\n", - tsk->comm, tsk->pid, sem); + printk("%s(%d:#%u): down acquired(%p)\n", + tsk->comm, tsk->pid, tsk->xid, sem); #endif } @@ -110,8 +110,8 @@ __down_failed_interruptible(struct semap long ret = 0; #ifdef CONFIG_DEBUG_SEMAPHORE - printk("%s(%d): down failed(%p)\n", - tsk->comm, tsk->pid, sem); + printk("%s(%d:#%u): down failed(%p)\n", + tsk->comm, tsk->pid, tsk->xid, sem); #endif tsk->state = TASK_INTERRUPTIBLE; diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/systbls.S linux-2.6.22.19-g-v/arch/alpha/kernel/systbls.S --- linux-2.6.22.19/arch/alpha/kernel/systbls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/systbls.S 2008-03-04 08:55:58.000000000 +0100 @@ -446,7 +446,7 @@ sys_call_table: .quad sys_stat64 /* 425 */ .quad sys_lstat64 .quad sys_fstat64 - .quad sys_ni_syscall /* sys_vserver */ + .quad sys_vserver /* sys_vserver */ .quad sys_ni_syscall /* sys_mbind */ .quad sys_ni_syscall /* sys_get_mempolicy */ .quad sys_ni_syscall /* sys_set_mempolicy */ diff -NurpP --minimal linux-2.6.22.19/arch/alpha/kernel/traps.c linux-2.6.22.19-g-v/arch/alpha/kernel/traps.c --- linux-2.6.22.19/arch/alpha/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/kernel/traps.c 2008-03-04 08:55:58.000000000 +0100 @@ -182,7 +182,8 @@ die_if_kernel(char * str, struct pt_regs #ifdef CONFIG_SMP printk("CPU %d ", hard_smp_processor_id()); #endif - printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); + printk("%s(%d[#%u]): %s %ld\n", current->comm, + current->pid, current->xid, str, err); dik_show_regs(regs, r9_15); dik_show_trace((unsigned long *)(regs+1)); dik_show_code((unsigned int *)regs->pc); diff -NurpP --minimal linux-2.6.22.19/arch/alpha/mm/fault.c linux-2.6.22.19-g-v/arch/alpha/mm/fault.c --- linux-2.6.22.19/arch/alpha/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/alpha/mm/fault.c 2008-03-04 08:55:58.000000000 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,124 @@ __load_new_mm_context(struct mm_struct * __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 + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + 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("???????? "); + else + printk("%08x ", c); + } + printk("\n"); +} +#endif /* * This routine handles page faults. It determines the address, @@ -131,8 +250,29 @@ do_page_fault(unsigned long address, uns 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 (!(mm->pax_flags & MF_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 + + } + 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))) @@ -197,8 +337,8 @@ do_page_fault(unsigned long address, uns down_read(&mm->mmap_sem); goto survive; } - printk(KERN_ALERT "VM: killing process %s(%d)\n", - current->comm, current->pid); + printk(KERN_ALERT "VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); if (!user_mode(regs)) goto no_context; do_exit(SIGKILL); diff -NurpP --minimal linux-2.6.22.19/arch/arm/Kconfig linux-2.6.22.19-g-v/arch/arm/Kconfig --- linux-2.6.22.19/arch/arm/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -1042,6 +1042,8 @@ source "arch/arm/oprofile/Kconfig" source "arch/arm/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/arm/kernel/calls.S linux-2.6.22.19-g-v/arch/arm/kernel/calls.S --- linux-2.6.22.19/arch/arm/kernel/calls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/kernel/calls.S 2008-03-04 08:55:58.000000000 +0100 @@ -322,7 +322,7 @@ /* 310 */ CALL(sys_request_key) CALL(sys_keyctl) CALL(ABI(sys_semtimedop, sys_oabi_semtimedop)) -/* vserver */ CALL(sys_ni_syscall) + CALL(sys_vserver) CALL(sys_ioprio_set) /* 315 */ CALL(sys_ioprio_get) CALL(sys_inotify_init) diff -NurpP --minimal linux-2.6.22.19/arch/arm/kernel/process.c linux-2.6.22.19-g-v/arch/arm/kernel/process.c --- linux-2.6.22.19/arch/arm/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/kernel/process.c 2008-03-04 08:55:58.000000000 +0100 @@ -261,7 +261,8 @@ void __show_regs(struct pt_regs *regs) void show_regs(struct pt_regs * regs) { printk("\n"); - printk("Pid: %d, comm: %20s\n", current->pid, current->comm); + printk("Pid: %d[#%u], comm: %20s\n", + current->pid, current->xid, current->comm); __show_regs(regs); __backtrace(); } @@ -423,7 +424,8 @@ pid_t kernel_thread(int (*fn)(void *), v regs.ARM_pc = (unsigned long)kernel_thread_helper; regs.ARM_cpsr = SVC_MODE; - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); diff -NurpP --minimal linux-2.6.22.19/arch/arm/kernel/traps.c linux-2.6.22.19-g-v/arch/arm/kernel/traps.c --- linux-2.6.22.19/arch/arm/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/kernel/traps.c 2008-03-04 08:55:58.000000000 +0100 @@ -222,8 +222,8 @@ static void __die(const char *str, int e str, err, ++die_counter); print_modules(); __show_regs(regs); - printk("Process %s (pid: %d, stack limit = 0x%p)\n", - tsk->comm, tsk->pid, thread + 1); + printk("Process %s (pid: %d:#%u, stack limit = 0x%p)\n", + tsk->comm, tsk->pid, tsk->xid, thread + 1); if (!user_mode(regs) || in_interrupt()) { dump_mem("Stack: ", regs->ARM_sp, diff -NurpP --minimal linux-2.6.22.19/arch/arm/mm/fault.c linux-2.6.22.19-g-v/arch/arm/mm/fault.c --- linux-2.6.22.19/arch/arm/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/mm/fault.c 2008-03-04 08:55:58.000000000 +0100 @@ -266,7 +266,8 @@ do_page_fault(unsigned long addr, unsign * happened to us that made us unable to handle * the page fault gracefully. */ - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); do_exit(SIGKILL); return 0; diff -NurpP --minimal linux-2.6.22.19/arch/arm/mm/mmap.c linux-2.6.22.19-g-v/arch/arm/mm/mmap.c --- linux-2.6.22.19/arch/arm/mm/mmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm/mm/mmap.c 2008-03-04 08:55:58.000000000 +0100 @@ -60,6 +60,10 @@ arch_get_unmapped_area(struct file *filp if (len > TASK_SIZE) return -ENOMEM; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + if (addr) { if (do_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -72,10 +76,10 @@ arch_get_unmapped_area(struct file *filp return addr; } if (len > mm->cached_hole_size) { - start_addr = addr = mm->free_area_cache; + start_addr = addr = mm->free_area_cache; } else { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; + start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; } full_search: @@ -91,8 +95,8 @@ full_search: * Start a new search - just in case we missed * some holes. */ - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; + if (start_addr != mm->mmap_base) { + start_addr = addr = mm->mmap_base; mm->cached_hole_size = 0; goto full_search; } diff -NurpP --minimal linux-2.6.22.19/arch/arm26/Kconfig linux-2.6.22.19-g-v/arch/arm26/Kconfig --- linux-2.6.22.19/arch/arm26/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm26/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -243,6 +243,8 @@ source "drivers/usb/Kconfig" source "arch/arm26/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/arm26/kernel/calls.S linux-2.6.22.19-g-v/arch/arm26/kernel/calls.S --- linux-2.6.22.19/arch/arm26/kernel/calls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm26/kernel/calls.S 2008-03-04 08:55:58.000000000 +0100 @@ -257,6 +257,11 @@ __syscall_start: .long sys_lremovexattr .long sys_fremovexattr .long sys_tkill + + .rept 313 - (. - __syscall_start) / 4 + .long sys_ni_syscall + .endr + .long sys_vserver /* 313 */ __syscall_end: .rept NR_syscalls - (__syscall_end - __syscall_start) / 4 diff -NurpP --minimal linux-2.6.22.19/arch/arm26/kernel/process.c linux-2.6.22.19-g-v/arch/arm26/kernel/process.c --- linux-2.6.22.19/arch/arm26/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm26/kernel/process.c 2008-03-04 08:55:58.000000000 +0100 @@ -365,7 +365,8 @@ pid_t kernel_thread(int (*fn)(void *), v regs.ARM_r3 = (unsigned long)do_exit; regs.ARM_pc = (unsigned long)kernel_thread_helper | MODE_SVC26; - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); diff -NurpP --minimal linux-2.6.22.19/arch/arm26/kernel/traps.c linux-2.6.22.19-g-v/arch/arm26/kernel/traps.c --- linux-2.6.22.19/arch/arm26/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/arm26/kernel/traps.c 2008-03-04 08:55:58.000000000 +0100 @@ -185,8 +185,9 @@ NORET_TYPE void die(const char *str, str printk("Internal error: %s: %x\n", str, err); printk("CPU: %d\n", smp_processor_id()); show_regs(regs); - printk("Process %s (pid: %d, stack limit = 0x%p)\n", - current->comm, current->pid, end_of_stack(tsk)); + printk("Process %s (pid: %d[#%u], stack limit = 0x%p)\n", + current->comm, current->pid, + current->xid, end_of_stack(tsk)); if (!user_mode(regs) || in_interrupt()) { __dump_stack(tsk, (unsigned long)(regs + 1)); diff -NurpP --minimal linux-2.6.22.19/arch/avr32/mm/fault.c linux-2.6.22.19-g-v/arch/avr32/mm/fault.c --- linux-2.6.22.19/arch/avr32/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/avr32/mm/fault.c 2008-03-04 08:55:58.000000000 +0100 @@ -41,6 +41,23 @@ static inline int notify_page_fault(stru int exception_trace = 1; +#ifdef CONFIG_PAX_PAGEEXEC +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("???????? "); + else + printk("%02x ", 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 routines. @@ -158,6 +175,16 @@ bad_area: up_read(&mm->mmap_sem); if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_PAX_PAGEEXEC) { + if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) { + pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp); + do_exit(SIGKILL); + } + } +#endif + if (exception_trace && printk_ratelimit()) printk("%s%s[%d]: segfault at %08lx pc %08lx " "sp %08lx ecr %lu\n", diff -NurpP --minimal linux-2.6.22.19/arch/cris/Kconfig linux-2.6.22.19-g-v/arch/cris/Kconfig --- linux-2.6.22.19/arch/cris/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/cris/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -200,6 +200,8 @@ source "drivers/usb/Kconfig" source "arch/cris/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/cris/arch-v10/kernel/process.c linux-2.6.22.19-g-v/arch/cris/arch-v10/kernel/process.c --- linux-2.6.22.19/arch/cris/arch-v10/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/cris/arch-v10/kernel/process.c 2008-03-04 08:55:58.000000000 +0100 @@ -103,7 +103,8 @@ int kernel_thread(int (*fn)(void *), voi regs.dccr = 1 << I_DCCR_BITNR; /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } /* setup the child's kernel stack with a pt_regs and switch_stack on it. diff -NurpP --minimal linux-2.6.22.19/arch/cris/arch-v32/kernel/process.c linux-2.6.22.19-g-v/arch/cris/arch-v32/kernel/process.c --- linux-2.6.22.19/arch/cris/arch-v32/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/cris/arch-v32/kernel/process.c 2008-03-04 08:55:58.000000000 +0100 @@ -120,7 +120,8 @@ kernel_thread(int (*fn)(void *), void * regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); /* Create the new process. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } /* diff -NurpP --minimal linux-2.6.22.19/arch/frv/kernel/kernel_thread.S linux-2.6.22.19-g-v/arch/frv/kernel/kernel_thread.S --- linux-2.6.22.19/arch/frv/kernel/kernel_thread.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/frv/kernel/kernel_thread.S 2008-03-04 08:55:58.000000000 +0100 @@ -13,6 +13,8 @@ #include #define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_KTHREAD 0x10000000 /* kernel thread */ +#define CLONE_KT (CLONE_VM | CLONE_KTHREAD) /* kernel thread flags */ #define KERN_ERR "<3>" .section .rodata @@ -37,7 +39,7 @@ kernel_thread: # start by forking the current process, but with shared VM setlos.p #__NR_clone,gr7 ; syscall number - ori gr10,#CLONE_VM,gr8 ; first syscall arg [clone_flags] + ori gr10,#CLONE_KT,gr8 ; first syscall arg [clone_flags] sethi.p #0xe4e4,gr9 ; second syscall arg [newsp] setlo #0xe4e4,gr9 setlos.p #0,gr10 ; third syscall arg [parent_tidptr] diff -NurpP --minimal linux-2.6.22.19/arch/h8300/Kconfig linux-2.6.22.19-g-v/arch/h8300/Kconfig --- linux-2.6.22.19/arch/h8300/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/h8300/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -222,6 +222,8 @@ source "fs/Kconfig" source "arch/h8300/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/h8300/kernel/process.c linux-2.6.22.19-g-v/arch/h8300/kernel/process.c --- linux-2.6.22.19/arch/h8300/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/h8300/kernel/process.c 2008-03-04 08:55:58.000000000 +0100 @@ -134,7 +134,7 @@ int kernel_thread(int (*fn)(void *), voi fs = get_fs(); set_fs (KERNEL_DS); - clone_arg = flags | CLONE_VM; + clone_arg = flags | CLONE_VM | CLONE_KTHREAD; __asm__("mov.l sp,er3\n\t" "sub.l er2,er2\n\t" "mov.l %2,er1\n\t" diff -NurpP --minimal linux-2.6.22.19/arch/i386/Kconfig linux-2.6.22.19-g-v/arch/i386/Kconfig --- linux-2.6.22.19/arch/i386/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/Kconfig 2008-03-04 08:55:58.000000000 +0100 @@ -586,7 +586,7 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT default 0x80000000 if VMSPLIT_2G - default 0x78000000 if VMSPLIT_2G_OPT + default 0x70000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000 @@ -815,7 +815,7 @@ config CRASH_DUMP config PHYSICAL_START hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) - default "0x100000" + default "0x200000" help This gives the physical address where the kernel is loaded. @@ -900,7 +900,7 @@ config HOTPLUG_CPU config COMPAT_VDSO bool "Compat VDSO support" - default y + default n help Map the VDSO to the predictable old-style address too. ---help--- @@ -1230,6 +1230,8 @@ endmenu source "arch/i386/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/i386/Kconfig.cpu linux-2.6.22.19-g-v/arch/i386/Kconfig.cpu --- linux-2.6.22.19/arch/i386/Kconfig.cpu 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/Kconfig.cpu 2008-03-04 08:55:58.000000000 +0100 @@ -274,7 +274,7 @@ config X86_PPRO_FENCE config X86_F00F_BUG bool - depends on M586MMX || M586TSC || M586 || M486 || M386 + depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC default y config X86_WP_WORKS_OK @@ -304,7 +304,7 @@ config X86_CMPXCHG64 config X86_ALIGNMENT_16 bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 default y config X86_GOOD_APIC diff -NurpP --minimal linux-2.6.22.19/arch/i386/Kconfig.debug linux-2.6.22.19-g-v/arch/i386/Kconfig.debug --- linux-2.6.22.19/arch/i386/Kconfig.debug 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/Kconfig.debug 2008-03-04 08:55:58.000000000 +0100 @@ -46,16 +46,6 @@ config DEBUG_PAGEALLOC This results in a large slowdown, but helps to find certain types of memory corruptions. -config DEBUG_RODATA - bool "Write protect kernel read-only data structures" - depends on DEBUG_KERNEL - help - Mark the kernel read-only data as write-protected in the pagetables, - in order to catch accidental (and incorrect) writes to such const - data. This option may have a slight performance impact because a - portion of the kernel code won't be covered by a 2MB TLB anymore. - If in doubt, say "N". - config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on DEBUG_KERNEL diff -NurpP --minimal linux-2.6.22.19/arch/i386/boot/setup.S linux-2.6.22.19-g-v/arch/i386/boot/setup.S --- linux-2.6.22.19/arch/i386/boot/setup.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/boot/setup.S 2008-03-04 08:55:58.000000000 +0100 @@ -893,11 +893,13 @@ startup_32: movl %eax, %gs movl %eax, %ss + movl 0x00000000, %ecx xorl %eax, %eax 1: incl %eax # check that A20 really IS enabled movl %eax, 0x00000000 # loop forever if it isn't cmpl %eax, 0x00100000 je 1b + movl %ecx, 0x00000000 # Jump to the 32bit entry point jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi) diff -NurpP --minimal linux-2.6.22.19/arch/i386/boot/video.S linux-2.6.22.19-g-v/arch/i386/boot/video.S --- linux-2.6.22.19/arch/i386/boot/video.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/boot/video.S 2008-03-04 08:55:58.000000000 +0100 @@ -96,6 +96,7 @@ #define PARAM_LFB_PAGES 0x32 #define PARAM_VESA_ATTRIB 0x34 #define PARAM_CAPABILITIES 0x36 +#define PARAM_VESAPM_SIZE 0x3a /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ #ifdef CONFIG_VIDEO_RETAIN @@ -280,6 +281,7 @@ dac_done: movw %es, %fs:(PARAM_VESAPM_SEG) movw %di, %fs:(PARAM_VESAPM_OFF) + movw %cx, %fs:(PARAM_VESAPM_SIZE) no_pm: ret # The video mode menu diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/acpi/boot.c linux-2.6.22.19-g-v/arch/i386/kernel/acpi/boot.c --- linux-2.6.22.19/arch/i386/kernel/acpi/boot.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/acpi/boot.c 2008-03-04 08:55:58.000000000 +0100 @@ -1095,7 +1095,7 @@ static struct dmi_system_id __initdata a DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), }, }, - {} + { NULL, NULL, {{0, NULL}}, NULL} }; #endif /* __i386__ */ diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/acpi/sleep.c linux-2.6.22.19-g-v/arch/i386/kernel/acpi/sleep.c --- linux-2.6.22.19/arch/i386/kernel/acpi/sleep.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/acpi/sleep.c 2008-03-04 08:55:58.000000000 +0100 @@ -94,7 +94,7 @@ static __initdata struct dmi_system_id a DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), }, }, - {} + { NULL, NULL, {{0, NULL}}, NULL} }; static int __init acpisleep_dmi_init(void) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/acpi/wakeup.S linux-2.6.22.19-g-v/arch/i386/kernel/acpi/wakeup.S --- linux-2.6.22.19/arch/i386/kernel/acpi/wakeup.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/acpi/wakeup.S 2008-03-04 08:55:58.000000000 +0100 @@ -2,6 +2,7 @@ #include #include #include +#include # # wakeup_code runs in real mode, and at unknown address (determined at run-time). @@ -64,7 +65,7 @@ wakeup_code: # restore efer setting movl real_save_efer_edx - wakeup_code, %edx movl real_save_efer_eax - wakeup_code, %eax - mov $0xc0000080, %ecx + mov $MSR_EFER, %ecx wrmsr 4: # make sure %cr4 is set correctly (features, etc) @@ -205,13 +206,11 @@ wakeup_pmode_return: # and restore the stack ... but you need gdt for this to work movl saved_context_esp, %esp - movl %cs:saved_magic, %eax - cmpl $0x12345678, %eax + cmpl $0x12345678, saved_magic jne bogus_magic # jump to place where we left off - movl saved_eip,%eax - jmp *%eax + jmp *(saved_eip) bogus_magic: movw $0x0e00 + 'B', 0xb8018 @@ -243,7 +242,7 @@ ENTRY(acpi_copy_wakeup_routine) # save efer setting pushl %eax movl %eax, %ebx - mov $0xc0000080, %ecx + mov $MSR_EFER, %ecx rdmsr movl %edx, real_save_efer_edx - wakeup_start (%ebx) movl %eax, real_save_efer_eax - wakeup_start (%ebx) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/alternative.c linux-2.6.22.19-g-v/arch/i386/kernel/alternative.c --- linux-2.6.22.19/arch/i386/kernel/alternative.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/alternative.c 2008-03-04 08:55:58.000000000 +0100 @@ -4,6 +4,7 @@ #include #include #include +#include static int noreplace_smp = 0; static int smp_alt_once = 0; @@ -165,12 +166,18 @@ void apply_alternatives(struct alt_instr u8 *instr; int diff; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; + + pax_open_kernel(cr0); +#endif + DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); for (a = start; a < end; a++) { BUG_ON(a->replacementlen > a->instrlen); if (!boot_cpu_has(a->cpuid)) continue; - instr = a->instr; + instr = a->instr + __KERNEL_TEXT_OFFSET; #ifdef CONFIG_X86_64 /* vsyscall code is not mapped yet. resolve it manually. */ if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) { @@ -183,6 +190,11 @@ void apply_alternatives(struct alt_instr diff = a->instrlen - a->replacementlen; nop_out(instr + a->replacementlen, diff); } + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + } #ifdef CONFIG_SMP @@ -191,29 +203,53 @@ static void alternatives_smp_lock(u8 **s { u8 **ptr; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; + + pax_open_kernel(cr0); +#endif + for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; if (*ptr > text_end) continue; - **ptr = 0xf0; /* lock prefix */ - }; + *(*ptr + __KERNEL_TEXT_OFFSET) = 0xf0; /* lock prefix */ + } + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + } static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) { u8 **ptr; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + if (noreplace_smp) return; +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; if (*ptr > text_end) continue; - nop_out(*ptr, 1); - }; + nop_out(*ptr + __KERNEL_TEXT_OFFSET, 1); + } + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + } struct smp_alt_module { @@ -340,21 +376,34 @@ void apply_paravirt(struct paravirt_patc { struct paravirt_patch_site *p; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + if (noreplace_paravirt) return; +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + for (p = start; p < end; p++) { unsigned int used; + u8 *instr = p->instr + __KERNEL_TEXT_OFFSET; - used = paravirt_ops.patch(p->instrtype, p->clobbers, p->instr, + used = paravirt_ops.patch(p->instrtype, p->clobbers, instr, p->len); BUG_ON(used > p->len); /* Pad the rest with nops */ - nop_out(p->instr + used, p->len - used); + nop_out(instr + used, p->len - used); } +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + /* Sync to be conservative, in case we patched following * instructions */ sync_core(); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/apm.c linux-2.6.22.19-g-v/arch/i386/kernel/apm.c --- linux-2.6.22.19/arch/i386/kernel/apm.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/apm.c 2008-03-04 08:55:58.000000000 +0100 @@ -600,9 +600,18 @@ static u8 apm_bios_call(u32 func, u32 eb struct desc_struct save_desc_40; struct desc_struct *gdt; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + cpus = apm_save_cpus(); cpu = get_cpu(); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; @@ -613,6 +622,11 @@ static u8 apm_bios_call(u32 func, u32 eb APM_DO_RESTORE_SEGS; apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + put_cpu(); apm_restore_cpus(cpus); @@ -643,9 +657,18 @@ static u8 apm_bios_call_simple(u32 func, struct desc_struct save_desc_40; struct desc_struct *gdt; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + cpus = apm_save_cpus(); cpu = get_cpu(); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; @@ -656,6 +679,11 @@ static u8 apm_bios_call_simple(u32 func, APM_DO_RESTORE_SEGS; apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + put_cpu(); apm_restore_cpus(cpus); return error; @@ -923,7 +951,7 @@ recalc: static void apm_power_off(void) { - unsigned char po_bios_call[] = { + const unsigned char po_bios_call[] = { 0xb8, 0x00, 0x10, /* movw $0x1000,ax */ 0x8e, 0xd0, /* movw ax,ss */ 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */ @@ -1863,7 +1891,10 @@ static const struct file_operations apm_ static struct miscdevice apm_device = { APM_MINOR_DEV, "apm_bios", - &apm_bios_fops + &apm_bios_fops, + {NULL, NULL}, + NULL, + NULL }; @@ -1973,210 +2004,210 @@ static struct dmi_system_id __initdata a print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), - DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), }, + DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), }, NULL }, { /* Handle problems with APM on the C600 */ broken_ps2_resume, "Dell Latitude C600", { DMI_MATCH(DMI_SYS_VENDOR, "Dell"), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), }, + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), }, NULL }, { /* Allow interrupts during suspend on Dell Latitude laptops*/ set_apm_ints, "Dell Latitude", { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), } + DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }, NULL }, { /* APM crashes */ apm_is_horked, "Dell Inspiron 2500", { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"), DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, + DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, NULL }, { /* Allow interrupts during suspend on Dell Inspiron laptops*/ set_apm_ints, "Dell Inspiron", { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), }, + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), }, NULL }, { /* Handle problems with APM on Inspiron 5000e */ broken_apm_power, "Dell Inspiron 5000e", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "A04"), - DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), }, + DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), }, NULL }, { /* Handle problems with APM on Inspiron 2500 */ broken_apm_power, "Dell Inspiron 2500", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "A12"), - DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), }, + DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), }, NULL }, { /* APM crashes */ apm_is_horked, "Dell Dimension 4100", { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), DMI_MATCH(DMI_BIOS_VENDOR,"Intel Corp."), - DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, + DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, NULL }, { /* Allow interrupts during suspend on Compaq Laptops*/ set_apm_ints, "Compaq 12XL125", { DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"), DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"4.06"), }, + DMI_MATCH(DMI_BIOS_VERSION,"4.06"), }, NULL }, { /* Allow interrupts during APM or the clock goes slow */ set_apm_ints, "ASUSTeK", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), }, + DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), }, NULL }, { /* APM blows on shutdown */ apm_is_horked, "ABIT KX7-333[R]", { DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"), - DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), }, + DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), }, NULL }, { /* APM crashes */ apm_is_horked, "Trigem Delhi3", { DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"), - DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), }, + DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), }, NULL }, { /* APM crashes */ apm_is_horked, "Fujitsu-Siemens", { DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"), - DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), }, + DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), }, NULL }, { /* APM crashes */ apm_is_horked_d850md, "Intel D850MD", { DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."), - DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), }, + DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), }, NULL }, { /* APM crashes */ apm_is_horked, "Intel D810EMO", { DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."), - DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), }, + DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), }, NULL }, { /* APM crashes */ apm_is_horked, "Dell XPS-Z", { DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."), DMI_MATCH(DMI_BIOS_VERSION, "A11"), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), }, + DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), }, NULL }, { /* APM crashes */ apm_is_horked, "Sharp PC-PJ/AX", { DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"), DMI_MATCH(DMI_BIOS_VENDOR,"SystemSoft"), - DMI_MATCH(DMI_BIOS_VERSION,"Version R2.08"), }, + DMI_MATCH(DMI_BIOS_VERSION,"Version R2.08"), }, NULL }, { /* APM crashes */ apm_is_horked, "Dell Inspiron 2500", { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"), DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, + DMI_MATCH(DMI_BIOS_VERSION,"A11"), }, NULL }, { /* APM idle hangs */ apm_likes_to_melt, "Jabil AMD", { DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), - DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), }, + DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), }, NULL }, { /* APM idle hangs */ apm_likes_to_melt, "AMI Bios", { DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), - DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), }, + DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0206H"), - DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), }, + DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-N505VX */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"), - DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-XG29 */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"), - DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z600NE */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"), - DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z600NE */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"), - DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"), - DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"), - DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z505LS */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"), - DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"), - DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), }, + DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-F104K */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"), - DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"), - DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-C1VE */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"), - DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), }, + DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), }, NULL }, { /* Handle problems with APM on Sony Vaio PCG-C1VE */ swab_apm_power_in_minutes, "Sony VAIO", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"), - DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), }, + DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), }, NULL }, { /* broken PM poweroff bios */ set_realmode_power_off, "Award Software v4.60 PGMA", { DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."), DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"), - DMI_MATCH(DMI_BIOS_DATE, "134526184"), }, + DMI_MATCH(DMI_BIOS_DATE, "134526184"), }, NULL }, /* Generic per vendor APM settings */ { /* Allow interrupts during suspend on IBM laptops */ set_apm_ints, "IBM", - { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, + { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, NULL }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL} }; /* @@ -2195,6 +2226,10 @@ static int __init apm_init(void) struct desc_struct *gdt; int err; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + dmi_check_system(apm_dmi_table); if (apm_info.bios.version == 0 || paravirt_enabled()) { @@ -2291,6 +2326,11 @@ static int __init apm_init(void) * code to that CPU. */ gdt = get_cpu_gdt_table(0); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + set_base(gdt[APM_CS >> 3], __va((unsigned long)apm_info.bios.cseg << 4)); set_base(gdt[APM_CS_16 >> 3], @@ -2298,6 +2338,10 @@ static int __init apm_init(void) set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + apm_proc = create_proc_entry("apm", 0, NULL); if (apm_proc) apm_proc->proc_fops = &apm_file_ops; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/asm-offsets.c linux-2.6.22.19-g-v/arch/i386/kernel/asm-offsets.c --- linux-2.6.22.19/arch/i386/kernel/asm-offsets.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/asm-offsets.c 2008-03-04 08:55:58.000000000 +0100 @@ -55,6 +55,7 @@ void foo(void) OFFSET(TI_exec_domain, thread_info, exec_domain); OFFSET(TI_flags, thread_info, flags); OFFSET(TI_status, thread_info, status); + OFFSET(TI_cpu, thread_info, cpu); OFFSET(TI_preempt_count, thread_info, preempt_count); OFFSET(TI_addr_limit, thread_info, addr_limit); OFFSET(TI_restart_block, thread_info, restart_block); @@ -101,6 +102,7 @@ void foo(void) DEFINE(PTRS_PER_PTE, PTRS_PER_PTE); DEFINE(PTRS_PER_PMD, PTRS_PER_PMD); DEFINE(PTRS_PER_PGD, PTRS_PER_PGD); + DEFINE(PERCPU_MODULE_RESERVE, PERCPU_MODULE_RESERVE); DEFINE(VDSO_PRELINK_asm, VDSO_PRELINK); @@ -114,5 +116,6 @@ void foo(void) OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); OFFSET(PARAVIRT_iret, paravirt_ops, iret); OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); + OFFSET(PARAVIRT_write_cr0, paravirt_ops, write_cr0); #endif } diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/common.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/common.c --- linux-2.6.22.19/arch/i386/kernel/cpu/common.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/common.c 2008-03-04 08:55:59.000000000 +0100 @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -21,39 +20,15 @@ #include "cpu.h" -DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { - [GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 }, - [GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 }, - [GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 }, - [GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 }, - /* - * Segments used for calling PnP BIOS have byte granularity. - * They code segments and data segments have fixed 64k limits, - * the transfer segment sizes are set at run time. - */ - [GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */ - [GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */ - [GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */ - /* - * The APM segments have byte granularity and their bases - * are set at run time. All have 64k limits. - */ - [GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */ - /* 16-bit code */ - [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 }, - [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */ - - [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 }, - [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 }, -} }; -EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); - static int cachesize_override __cpuinitdata = -1; static int disable_x86_fxsr __cpuinitdata; static int disable_x86_serial_nr __cpuinitdata = 1; -static int disable_x86_sep __cpuinitdata; + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +int disable_x86_sep __cpuinitdata = 1; +#else +int disable_x86_sep __cpuinitdata; +#endif struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; @@ -261,10 +236,10 @@ static int __cpuinit have_cpuid_p(void) void __init cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ - cpuid(0x00000000, &c->cpuid_level, - (int *)&c->x86_vendor_id[0], - (int *)&c->x86_vendor_id[8], - (int *)&c->x86_vendor_id[4]); + cpuid(0x00000000, (unsigned int *)&c->cpuid_level, + (unsigned int *)&c->x86_vendor_id[0], + (unsigned int *)&c->x86_vendor_id[8], + (unsigned int *)&c->x86_vendor_id[4]); c->x86 = 4; if (c->cpuid_level >= 0x00000001) { @@ -304,15 +279,14 @@ static void __init early_cpu_detect(void static void __cpuinit generic_identify(struct cpuinfo_x86 * c) { - u32 tfms, xlvl; - int ebx; + u32 tfms, xlvl, ebx; if (have_cpuid_p()) { /* Get vendor name */ - cpuid(0x00000000, &c->cpuid_level, - (int *)&c->x86_vendor_id[0], - (int *)&c->x86_vendor_id[8], - (int *)&c->x86_vendor_id[4]); + cpuid(0x00000000, (unsigned int *)&c->cpuid_level, + (unsigned int *)&c->x86_vendor_id[0], + (unsigned int *)&c->x86_vendor_id[8], + (unsigned int *)&c->x86_vendor_id[4]); get_cpu_vendor(c, 0); /* Initialize the standard set of capabilities */ @@ -644,7 +618,7 @@ void switch_to_new_gdt(void) { struct Xgt_desc_struct gdt_descr; - gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); + gdt_descr.address = get_cpu_gdt_table(smp_processor_id()); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); asm("mov %0, %%fs" : : "r" (__KERNEL_PERCPU) : "memory"); @@ -660,7 +634,7 @@ void __cpuinit cpu_init(void) { int cpu = smp_processor_id(); struct task_struct *curr = current; - struct tss_struct * t = &per_cpu(init_tss, cpu); + struct tss_struct *t = init_tss + cpu; struct thread_struct *thread = &curr->thread; if (cpu_test_and_set(cpu, cpu_initialized)) { diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c --- linux-2.6.22.19/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c 2008-03-04 08:55:59.000000000 +0100 @@ -560,7 +560,7 @@ static struct dmi_system_id sw_any_bug_d DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; #endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c --- linux-2.6.22.19/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2008-03-04 08:55:59.000000000 +0100 @@ -229,7 +229,7 @@ static struct cpu_model models[] = { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, - { NULL, } + { NULL, NULL, 0, NULL} }; #undef _BANIAS #undef BANIAS @@ -404,7 +404,7 @@ static struct dmi_system_id sw_any_bug_d DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; #endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/intel_cacheinfo.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/intel_cacheinfo.c --- linux-2.6.22.19/arch/i386/kernel/cpu/intel_cacheinfo.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/intel_cacheinfo.c 2008-03-04 08:55:59.000000000 +0100 @@ -318,8 +318,8 @@ unsigned int __cpuinit init_intel_cachei */ if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) { /* supports eax=2 call */ - int i, j, n; - int regs[4]; + int j, n; + unsigned int regs[4]; unsigned char *dp = (unsigned char *)regs; int only_trace = 0; @@ -334,7 +334,7 @@ unsigned int __cpuinit init_intel_cachei /* If bit 31 is set, this is an unknown format */ for ( j = 0 ; j < 3 ; j++ ) { - if ( regs[j] < 0 ) regs[j] = 0; + if ( (int)regs[j] < 0 ) regs[j] = 0; } /* Byte 0 is level count, not a descriptor */ diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/mcheck/therm_throt.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/mcheck/therm_throt.c --- linux-2.6.22.19/arch/i386/kernel/cpu/mcheck/therm_throt.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/mcheck/therm_throt.c 2008-03-04 08:55:59.000000000 +0100 @@ -150,7 +150,7 @@ static __cpuinit int thermal_throttle_cp return NOTIFY_OK; } -static struct notifier_block thermal_throttle_cpu_notifier = +static __cpuinitdata struct notifier_block thermal_throttle_cpu_notifier = { .notifier_call = thermal_throttle_cpu_callback, }; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/cpu/mtrr/generic.c linux-2.6.22.19-g-v/arch/i386/kernel/cpu/mtrr/generic.c --- linux-2.6.22.19/arch/i386/kernel/cpu/mtrr/generic.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/cpu/mtrr/generic.c 2008-03-04 08:55:59.000000000 +0100 @@ -29,11 +29,11 @@ static struct fixed_range_block fixed_ra { MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */ { MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */ { MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */ - {} + { 0, 0 } }; static unsigned long smp_changes_mask; -static struct mtrr_state mtrr_state = {}; +static struct mtrr_state mtrr_state; #undef MODULE_PARAM_PREFIX #define MODULE_PARAM_PREFIX "mtrr." @@ -79,7 +79,7 @@ static void print_fixed(unsigned base, u } /* Grab all of the MTRR state for this CPU into *state */ -void get_mtrr_state(void) +void __init get_mtrr_state(void) { unsigned int i; struct mtrr_var_range *vrs; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/crash.c linux-2.6.22.19-g-v/arch/i386/kernel/crash.c --- linux-2.6.22.19/arch/i386/kernel/crash.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/crash.c 2008-03-04 08:55:59.000000000 +0100 @@ -55,7 +55,7 @@ static int crash_nmi_callback(struct not return NOTIFY_STOP; local_irq_disable(); - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/doublefault.c linux-2.6.22.19-g-v/arch/i386/kernel/doublefault.c --- linux-2.6.22.19/arch/i386/kernel/doublefault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/doublefault.c 2008-03-04 08:55:59.000000000 +0100 @@ -11,17 +11,17 @@ #define DOUBLEFAULT_STACKSIZE (1024) static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; -#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) +#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2) #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) static void doublefault_fn(void) { - struct Xgt_desc_struct gdt_desc = {0, 0}; + struct Xgt_desc_struct gdt_desc = {0, NULL, 0}; unsigned long gdt, tss; store_gdt(&gdt_desc); - gdt = gdt_desc.address; + gdt = (unsigned long)gdt_desc.address; printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); @@ -59,10 +59,10 @@ struct tss_struct doublefault_tss __cach /* 0x2 bit is always set */ .eflags = X86_EFLAGS_SF | 0x2, .esp = STACK_START, - .es = __USER_DS, + .es = __KERNEL_DS, .cs = __KERNEL_CS, .ss = __KERNEL_DS, - .ds = __USER_DS, + .ds = __KERNEL_DS, .fs = __KERNEL_PERCPU, .__cr3 = __pa(swapper_pg_dir) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/efi.c linux-2.6.22.19-g-v/arch/i386/kernel/efi.c --- linux-2.6.22.19/arch/i386/kernel/efi.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/efi.c 2008-03-04 08:55:59.000000000 +0100 @@ -63,45 +63,23 @@ extern void * boot_ioremap(unsigned long static unsigned long efi_rt_eflags; static DEFINE_SPINLOCK(efi_rt_lock); -static pgd_t efi_bak_pg_dir_pointer[2]; +static pgd_t __initdata efi_bak_pg_dir_pointer[KERNEL_PGD_PTRS] __attribute__ ((aligned (4096))); static void efi_call_phys_prelog(void) __acquires(efi_rt_lock) { - unsigned long cr4; - unsigned long temp; struct Xgt_desc_struct gdt_descr; spin_lock(&efi_rt_lock); local_irq_save(efi_rt_eflags); - /* - * If I don't have PSE, I should just duplicate two entries in page - * directory. If I have PSE, I just need to duplicate one entry in - * page directory. - */ - cr4 = read_cr4(); - - if (cr4 & X86_CR4_PSE) { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - swapper_pg_dir[0].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - } else { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - efi_bak_pg_dir_pointer[1].pgd = - swapper_pg_dir[pgd_index(0x400000)].pgd; - swapper_pg_dir[pgd_index(0)].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - temp = PAGE_OFFSET + 0x400000; - swapper_pg_dir[pgd_index(0x400000)].pgd = - swapper_pg_dir[pgd_index(temp)].pgd; - } + clone_pgd_range(efi_bak_pg_dir_pointer, swapper_pg_dir, KERNEL_PGD_PTRS); + clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); /* * After the lock is released, the original page table is restored. */ - local_flush_tlb(); + __flush_tlb_all(); gdt_descr.address = __pa(get_cpu_gdt_table(0)); gdt_descr.size = GDT_SIZE - 1; @@ -110,35 +88,24 @@ static void efi_call_phys_prelog(void) _ static void efi_call_phys_epilog(void) __releases(efi_rt_lock) { - unsigned long cr4; struct Xgt_desc_struct gdt_descr; - gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); + gdt_descr.address = get_cpu_gdt_table(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); - cr4 = read_cr4(); - - if (cr4 & X86_CR4_PSE) { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - } else { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - swapper_pg_dir[pgd_index(0x400000)].pgd = - efi_bak_pg_dir_pointer[1].pgd; - } + clone_pgd_range(swapper_pg_dir, efi_bak_pg_dir_pointer, KERNEL_PGD_PTRS); /* * After the lock is released, the original page table is restored. */ - local_flush_tlb(); + __flush_tlb_all(); local_irq_restore(efi_rt_eflags); spin_unlock(&efi_rt_lock); } -static efi_status_t +static efi_status_t __init phys_efi_set_virtual_address_map(unsigned long memory_map_size, unsigned long descriptor_size, u32 descriptor_version, @@ -154,7 +121,7 @@ phys_efi_set_virtual_address_map(unsigne return status; } -static efi_status_t +static efi_status_t __init phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { efi_status_t status; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/efi_stub.S linux-2.6.22.19-g-v/arch/i386/kernel/efi_stub.S --- linux-2.6.22.19/arch/i386/kernel/efi_stub.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/efi_stub.S 2008-03-04 08:55:59.000000000 +0100 @@ -6,6 +6,7 @@ */ #include +#include #include /* @@ -20,7 +21,7 @@ * service functions will comply with gcc calling convention, too. */ -.text +__INIT ENTRY(efi_call_phys) /* * 0. The function can only be called in Linux kernel. So CS has been @@ -36,9 +37,7 @@ ENTRY(efi_call_phys) * The mapping of lower virtual memory has been created in prelog and * epilog. */ - movl $1f, %edx - subl $__PAGE_OFFSET, %edx - jmp *%edx + jmp 1f-__PAGE_OFFSET 1: /* @@ -47,14 +46,8 @@ ENTRY(efi_call_phys) * parameter 2, ..., param n. To make things easy, we save the return * address of efi_call_phys in a global variable. */ - popl %edx - movl %edx, saved_return_addr - /* get the function pointer into ECX*/ - popl %ecx - movl %ecx, efi_rt_function_ptr - movl $2f, %edx - subl $__PAGE_OFFSET, %edx - pushl %edx + popl (saved_return_addr) + popl (efi_rt_function_ptr) /* * 3. Clear PG bit in %CR0. @@ -73,9 +66,8 @@ ENTRY(efi_call_phys) /* * 5. Call the physical function. */ - jmp *%ecx + call *(efi_rt_function_ptr-__PAGE_OFFSET) -2: /* * 6. After EFI runtime service returns, control will return to * following instruction. We'd better readjust stack pointer first. @@ -85,37 +77,29 @@ ENTRY(efi_call_phys) /* * 7. Restore PG bit */ - movl %cr0, %edx - orl $0x80000000, %edx - movl %edx, %cr0 - jmp 1f -1: /* * 8. Now restore the virtual mode from flat mode by * adding EIP with PAGE_OFFSET. */ - movl $1f, %edx - jmp *%edx + movl %cr0, %edx + orl $0x80000000, %edx + movl %edx, %cr0 + jmp 1f+__PAGE_OFFSET 1: /* * 9. Balance the stack. And because EAX contain the return value, * we'd better not clobber it. */ - leal efi_rt_function_ptr, %edx - movl (%edx), %ecx - pushl %ecx + pushl (efi_rt_function_ptr) /* - * 10. Push the saved return address onto the stack and return. + * 10. Return to the saved return address. */ - leal saved_return_addr, %edx - movl (%edx), %ecx - pushl %ecx - ret + jmpl *(saved_return_addr) .previous -.data +__INITDATA saved_return_addr: .long 0 efi_rt_function_ptr: diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/entry.S linux-2.6.22.19-g-v/arch/i386/kernel/entry.S --- linux-2.6.22.19/arch/i386/kernel/entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/entry.S 2008-03-04 08:55:59.000000000 +0100 @@ -97,7 +97,7 @@ VM_MASK = 0x00020000 #define resume_userspace_sig resume_userspace #endif -#define SAVE_ALL \ +#define __SAVE_ALL(_DS) \ cld; \ pushl %fs; \ CFI_ADJUST_CFA_OFFSET 4;\ @@ -129,12 +129,26 @@ VM_MASK = 0x00020000 pushl %ebx; \ CFI_ADJUST_CFA_OFFSET 4;\ CFI_REL_OFFSET ebx, 0;\ - movl $(__USER_DS), %edx; \ + movl $(_DS), %edx; \ movl %edx, %ds; \ movl %edx, %es; \ movl $(__KERNEL_PERCPU), %edx; \ movl %edx, %fs +#ifdef CONFIG_PAX_KERNEXEC +#define SAVE_ALL \ + __SAVE_ALL(__KERNEL_DS); \ + GET_CR0_INTO_EDX; \ + movl %edx, %esi; \ + orl $X86_CR0_WP, %edx; \ + xorl %edx, %esi; \ + SET_CR0_FROM_EDX +#elif defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +#define SAVE_ALL __SAVE_ALL(__KERNEL_DS) +#else +#define SAVE_ALL __SAVE_ALL(__USER_DS) +#endif + #define RESTORE_INT_REGS \ popl %ebx; \ CFI_ADJUST_CFA_OFFSET -4;\ @@ -248,7 +262,17 @@ check_userspace: movb PT_CS(%esp), %al andl $(VM_MASK | SEGMENT_RPL_MASK), %eax cmpl $USER_RPL, %eax + +#ifdef CONFIG_PAX_KERNEXEC + jae resume_userspace + + GET_CR0_INTO_EDX + xorl %esi, %edx + SET_CR0_FROM_EDX + jmp resume_kernel +#else jb resume_kernel # not returning to v8086 or userspace +#endif ENTRY(resume_userspace) DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt @@ -307,10 +331,9 @@ sysenter_past_esp: /*CFI_REL_OFFSET cs, 0*/ /* * Push current_thread_info()->sysenter_return to the stack. - * A tiny bit of offset fixup is necessary - 4*4 means the 4 words - * pushed above; +8 corresponds to copy_thread's esp0 setting. */ - pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) + GET_THREAD_INFO(%ebp) + pushl TI_sysenter_return(%ebp) CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET eip, 0 @@ -318,9 +341,17 @@ sysenter_past_esp: * Load the potential sixth argument from user stack. * Careful about security. */ + movl 12(%esp),%ebp + +#ifdef CONFIG_PAX_MEMORY_UDEREF + mov 16(%esp),%ds +1: movl %ds:(%ebp),%ebp +#else cmpl $__PAGE_OFFSET-3,%ebp jae syscall_fault 1: movl (%ebp),%ebp +#endif + .section __ex_table,"a" .align 4 .long 1b,syscall_fault @@ -343,20 +374,37 @@ sysenter_past_esp: movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx jne syscall_exit_work + +#ifdef CONFIG_PAX_RANDKSTACK + pushl %eax + CFI_ADJUST_CFA_OFFSET 4 + call pax_randomize_kstack + popl %eax + CFI_ADJUST_CFA_OFFSET -4 +#endif + /* if something modifies registers it must also disable sysexit */ movl PT_EIP(%esp), %edx movl PT_OLDESP(%esp), %ecx xorl %ebp,%ebp TRACE_IRQS_ON 1: mov PT_FS(%esp), %fs +2: mov PT_DS(%esp), %ds +3: mov PT_ES(%esp), %es ENABLE_INTERRUPTS_SYSEXIT CFI_ENDPROC .pushsection .fixup,"ax" -2: movl $0,PT_FS(%esp) +4: movl $0,PT_FS(%esp) jmp 1b +5: movl $0,PT_DS(%esp) + jmp 2b +6: movl $0,PT_ES(%esp) + jmp 3b .section __ex_table,"a" .align 4 - .long 1b,2b + .long 1b,4b + .long 2b,5b + .long 3b,6b .popsection ENDPROC(sysenter_entry) @@ -389,6 +437,10 @@ no_singlestep: testw $_TIF_ALLWORK_MASK, %cx # current->work jne syscall_exit_work +#ifdef CONFIG_PAX_RANDKSTACK + call pax_randomize_kstack +#endif + restore_all: movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS # Warning: PT_OLDSS(%esp) contains the wrong/random values if we @@ -552,17 +604,24 @@ syscall_badsys: END(syscall_badsys) CFI_ENDPROC -#define FIXUP_ESPFIX_STACK \ - /* since we are on a wrong stack, we cant make it a C code :( */ \ - PER_CPU(gdt_page, %ebx); \ - GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \ - addl %esp, %eax; \ - pushl $__KERNEL_DS; \ - CFI_ADJUST_CFA_OFFSET 4; \ - pushl %eax; \ - CFI_ADJUST_CFA_OFFSET 4; \ - lss (%esp), %esp; \ +.macro FIXUP_ESPFIX_STACK + /* since we are on a wrong stack, we cant make it a C code :( */ +#ifdef CONFIG_SMP + movl PER_CPU_VAR(cpu_number), %ebx; + shll $PAGE_SHIFT_asm, %ebx; + addl $cpu_gdt_table, %ebx; +#else + movl $cpu_gdt_table, %ebx; +#endif + GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); + addl %esp, %eax; + pushl $__KERNEL_DS; + CFI_ADJUST_CFA_OFFSET 4; + pushl %eax; + CFI_ADJUST_CFA_OFFSET 4; + lss (%esp), %esp; CFI_ADJUST_CFA_OFFSET -8; +.endm #define UNWIND_ESPFIX_STACK \ movl %ss, %eax; \ /* see if on espfix stack */ \ @@ -579,7 +638,7 @@ END(syscall_badsys) * Build the entry stubs and pointer table with * some assembler magic. */ -.data +.section .rodata,"a",@progbits ENTRY(interrupt) .text @@ -679,12 +738,21 @@ error_code: popl %ecx CFI_ADJUST_CFA_OFFSET -4 /*CFI_REGISTER es, ecx*/ + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_EDX + movl %edx, %esi + orl $X86_CR0_WP, %edx + xorl %edx, %esi + SET_CR0_FROM_EDX +#endif + movl PT_FS(%esp), %edi # get the function address movl PT_ORIG_EAX(%esp), %edx # get the error code movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart mov %ecx, PT_FS(%esp) /*CFI_REL_OFFSET fs, ES*/ - movl $(__USER_DS), %ecx + movl $(__KERNEL_DS), %ecx movl %ecx, %ds movl %ecx, %es movl %esp,%eax # pt_regs pointer @@ -818,6 +886,13 @@ nmi_stack_correct: xorl %edx,%edx # zero error code movl %esp,%eax # pt_regs pointer call do_nmi + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_EDX + xorl %esi, %edx + SET_CR0_FROM_EDX +#endif + jmp restore_nocheck_notrace CFI_ENDPROC @@ -858,6 +933,13 @@ nmi_espfix_stack: FIXUP_ESPFIX_STACK # %eax == %esp xorl %edx,%edx # zero error code call do_nmi + +#ifdef CONFIG_PAX_KERNEXEC + GET_CR0_INTO_EDX + xorl %esi, %edx + SET_CR0_FROM_EDX +#endif + RESTORE_REGS lss 12+4(%esp), %esp # back to espfix stack CFI_ADJUST_CFA_OFFSET -24 @@ -1021,7 +1103,6 @@ ENTRY(kernel_thread_helper) CFI_ENDPROC ENDPROC(kernel_thread_helper) -.section .rodata,"a" #include "syscall_table.S" syscall_table_size=(.-sys_call_table) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/head.S linux-2.6.22.19-g-v/arch/i386/kernel/head.S --- linux-2.6.22.19/arch/i386/kernel/head.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/head.S 2008-03-04 08:55:59.000000000 +0100 @@ -18,6 +18,7 @@ #include #include #include +#include /* * References to members of the new_cpu_data structure. @@ -51,16 +52,23 @@ */ LOW_PAGES = 1<<(32-PAGE_SHIFT_asm) -#if PTRS_PER_PMD > 1 -PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD -#else -PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD) -#endif +PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PTE) BOOTBITMAP_SIZE = LOW_PAGES / 8 ALLOCATOR_SLOP = 4 INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm +#ifdef CONFIG_PAX_KERNEXEC +/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */ +.fill 4096,1,0xcc +#endif + +/* + * 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. @@ -82,6 +90,43 @@ ENTRY(startup_32) movl %eax,%fs movl %eax,%gs + movl $__per_cpu_start,%eax + movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_PERCPU + 2) + rorl $16,%eax + movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_PERCPU + 4) + movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_PERCPU + 7) + movl $__per_cpu_end + PERCPU_MODULE_RESERVE,%eax + subl $__per_cpu_start,%eax + movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_PERCPU + 0) + +#ifdef CONFIG_PAX_MEMORY_UDEREF + /* check for VMware */ + movl $0x564d5868,%eax + xorl %ebx,%ebx + movl $0xa,%ecx + movl $0x5658,%edx + in (%dx),%eax + cmpl $0x564d5868,%ebx + jz 1f + + movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),%eax + movl %eax,(cpu_gdt_table - __PAGE_OFFSET + GDT_ENTRY_KERNEL_DS * 8 + 4) +1: +#endif + +#ifdef CONFIG_PAX_KERNEXEC + movl $__KERNEL_TEXT_OFFSET,%eax + movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2) + rorl $16,%eax + movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4) + movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7) + + movb %al,(boot_gdt - __PAGE_OFFSET + __BOOT_CS + 4) + movb %ah,(boot_gdt - __PAGE_OFFSET + __BOOT_CS + 7) + rorl $16,%eax + movw %ax,(boot_gdt - __PAGE_OFFSET + __BOOT_CS + 2) +#endif + /* * Clear BSS first so that there are no surprises... * No need to cld as DF is already clear from cld above... @@ -129,24 +174,42 @@ ENTRY(startup_32) * Warning: don't use %esi or the stack in this code. However, %esp * can be used as a GPR if you really need it... */ -page_pde_offset = (__PAGE_OFFSET >> 20); - +#ifdef CONFIG_X86_PAE +page_pde_offset = ((__PAGE_OFFSET >> 21) * (PAGE_SIZE_asm / PTRS_PER_PTE)); +#else +page_pde_offset = ((__PAGE_OFFSET >> 22) * (PAGE_SIZE_asm / PTRS_PER_PTE)); +#endif movl $(pg0 - __PAGE_OFFSET), %edi +#ifdef CONFIG_X86_PAE + movl $(swapper_pm_dir - __PAGE_OFFSET), %edx +#else movl $(swapper_pg_dir - __PAGE_OFFSET), %edx - movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ +#endif + movl $0x063, %eax /* 0x063 = DIRTY+ACCESSED+PRESENT+RW */ 10: - leal 0x007(%edi),%ecx /* Create PDE entry */ + leal 0x063(%edi),%ecx /* Create PDE entry */ movl %ecx,(%edx) /* Store identity PDE entry */ movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ +#ifdef CONFIG_X86_PAE + movl $0,4(%edx) + movl $0,page_pde_offset+4(%edx) + addl $8,%edx + movl $512, %ecx +#else addl $4,%edx movl $1024, %ecx +#endif 11: stosl +#ifdef CONFIG_X86_PAE + movl $0,(%edi) + addl $4,%edi +#endif 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 +0x063 is the attribute bits */ + leal (INIT_MAP_BEYOND_END+0x063)(%edi),%ebp cmpl %ebp,%eax jb 10b movl %edi,(init_pg_tables_end - __PAGE_OFFSET) @@ -177,6 +240,11 @@ ENTRY(startup_32_smp) movl %eax,%fs movl %eax,%gs + /* This is a secondary processor (AP) */ + xorl %ebx,%ebx + incl %ebx +#endif /* CONFIG_SMP */ + /* * New page tables may be in 4Mbyte page mode and may * be using the global pages. @@ -192,42 +260,47 @@ ENTRY(startup_32_smp) * not yet offset PAGE_OFFSET.. */ #define cr4_bits mmu_cr4_features-__PAGE_OFFSET +3: movl cr4_bits,%edx andl %edx,%edx - jz 6f + jz 5f movl %cr4,%eax # Turn on paging options (PSE,PAE,..) orl %edx,%eax movl %eax,%cr4 - btl $5, %eax # check if PAE is enabled - jnc 6f +#ifdef CONFIG_X86_PAE + movl %ebx,%edi /* Check if extended functions are implemented */ movl $0x80000000, %eax cpuid cmpl $0x80000000, %eax - jbe 6f + jbe 4f mov $0x80000001, %eax cpuid /* Execute Disable bit supported? */ btl $20, %edx - jnc 6f + jnc 4f /* Setup EFER (Extended Feature Enable Register) */ - movl $0xc0000080, %ecx + movl $MSR_EFER, %ecx rdmsr btsl $11, %eax /* Make changes effective */ wrmsr -6: - /* This is a secondary processor (AP) */ - xorl %ebx,%ebx - incl %ebx + btsl $63-32,__supported_pte_mask+4-__PAGE_OFFSET + movl $1,nx_enabled-__PAGE_OFFSET -#endif /* CONFIG_SMP */ -3: +#if !defined(CONFIG_PAX_SEGMEXEC) && !defined(CONFIG_PAX_KERNEXEC) && !defined(CONFIG_PAX_MEMORY_UDEREF) + movl $0,disable_x86_sep-__PAGE_OFFSET +#endif + +4: + movl %edi,%ebx +#endif +5: /* * Enable paging @@ -252,9 +325,7 @@ ENTRY(startup_32_smp) #ifdef CONFIG_SMP andl %ebx,%ebx - jz 1f /* Initial CPU cleans BSS */ - jmp checkCPUtype -1: + jnz checkCPUtype /* Initial CPU cleans BSS */ #endif /* CONFIG_SMP */ /* @@ -331,12 +402,12 @@ is386: movl $2,%ecx # set MP ljmp $(__KERNEL_CS),$1f 1: movl $(__KERNEL_DS),%eax # reload all the segment registers movl %eax,%ss # after changing gdt. - movl %eax,%fs # gets reset once there's real percpu - - movl $(__USER_DS),%eax # DS/ES contains default USER segment movl %eax,%ds movl %eax,%es + movl $(__KERNEL_PERCPU), %eax + movl %eax,%fs # set this cpu's percpu + xorl %eax,%eax # Clear GS and LDT movl %eax,%gs lldt %ax @@ -347,11 +418,7 @@ is386: movl $2,%ecx # set MP movb ready, %cl movb $1, ready cmpb $0,%cl # the first CPU calls start_kernel - je 1f - movl $(__KERNEL_PERCPU), %eax - movl %eax,%fs # set this cpu's percpu - jmp initialize_secondary # all other CPUs call initialize_secondary -1: + jne initialize_secondary # all other CPUs call initialize_secondary #endif /* CONFIG_SMP */ jmp start_kernel @@ -462,8 +529,8 @@ hlt_loop: /* This is the default interrupt "handler" :-) */ ALIGN ignore_int: - cld #ifdef CONFIG_PRINTK + cld pushl %eax pushl %ecx pushl %edx @@ -494,28 +561,54 @@ ignore_int: #endif iret -.section .text -/* - * Real beginning of normal "text" segment - */ -ENTRY(stext) -ENTRY(_stext) - /* * BSS section */ -.section ".bss.page_aligned","w" +.section .swapper_pg_dir,"a",@progbits ENTRY(swapper_pg_dir) +#ifdef CONFIG_X86_PAE + .long swapper_pm_dir-__PAGE_OFFSET+1 + .long 0 + .long swapper_pm_dir+512*8-__PAGE_OFFSET+1 + .long 0 + .long swapper_pm_dir+512*16-__PAGE_OFFSET+1 + .long 0 + .long swapper_pm_dir+512*24-__PAGE_OFFSET+1 + .long 0 +#else .fill 1024,4,0 +#endif + +#ifdef CONFIG_X86_PAE +.section .swapper_pm_dir,"a",@progbits +ENTRY(swapper_pm_dir) + .fill 512,8,0 + .fill 512,8,0 + .fill 512,8,0 + .fill 512,8,0 +#endif + +.section .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 .idt,"a",@progbits +ENTRY(idt_table) + .fill 256,8,0 + +/* * This starts the data section. */ .data + +.section .rodata,"a",@progbits ENTRY(stack_start) - .long init_thread_union+THREAD_SIZE + .long init_thread_union+THREAD_SIZE-8 .long __BOOT_DS ready: .byte 0 @@ -556,7 +649,7 @@ idt_descr: .word 0 # 32 bit align gdt_desc.address ENTRY(early_gdt_descr) .word GDT_ENTRIES*8-1 - .long per_cpu__gdt_page /* Overwritten for secondary CPUs */ + .long cpu_gdt_table /* Overwritten for secondary CPUs */ /* * The boot_gdt must mirror the equivalent in setup.S and is @@ -565,5 +658,61 @@ ENTRY(early_gdt_descr) .align L1_CACHE_BYTES ENTRY(boot_gdt) .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 */ + + .align PAGE_SIZE_asm +ENTRY(cpu_gdt_table) + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* 0x0b reserved */ + .quad 0x0000000000000000 /* 0x13 reserved */ + .quad 0x0000000000000000 /* 0x1b reserved */ + .quad 0x0000000000000000 /* 0x20 unused */ + .quad 0x0000000000000000 /* 0x28 unused */ + .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ + .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ + .quad 0x0000000000000000 /* 0x43 TLS entry 3 */ + .quad 0x0000000000000000 /* 0x4b reserved */ + .quad 0x0000000000000000 /* 0x53 reserved */ + .quad 0x0000000000000000 /* 0x5b reserved */ + + .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ + .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 have byte granularity. + * The code segments and data segments have fixed 64k limits, + * the transfer segment sizes are set at run time. + */ + .quad 0x00409b000000ffff /* 0x90 32-bit code */ + .quad 0x00009b000000ffff /* 0x98 16-bit code */ + .quad 0x000093000000ffff /* 0xa0 16-bit data */ + .quad 0x0000930000000000 /* 0xa8 16-bit data */ + .quad 0x0000930000000000 /* 0xb0 16-bit data */ + + /* + * The APM segments have byte granularity and their bases + * are set at run time. All have 64k limits. + */ + .quad 0x00409b000000ffff /* 0xb8 APM CS code */ + .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */ + .quad 0x004093000000ffff /* 0xc8 APM DS data */ + + .quad 0x00c0930000000000 /* 0xd0 - ESPFIX SS */ + .quad 0x0040930000000000 /* 0xd8 - PERCPU */ + .quad 0x0000000000000000 /* 0xe0 - PCIBIOS_CS */ + .quad 0x0000000000000000 /* 0xe8 - PCIBIOS_DS */ + .quad 0x0000000000000000 /* 0xf0 - unused */ + .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ + + /* Be sure this is zeroed to avoid false validations in Xen */ + .fill PAGE_SIZE_asm - GDT_ENTRIES,1,0 + +#ifdef CONFIG_SMP + .fill (NR_CPUS-1) * (PAGE_SIZE_asm),1,0 /* other CPU's GDT */ +#endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/hpet.c linux-2.6.22.19-g-v/arch/i386/kernel/hpet.c --- linux-2.6.22.19/arch/i386/kernel/hpet.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/hpet.c 2008-03-04 08:55:59.000000000 +0100 @@ -95,7 +95,7 @@ static void hpet_reserve_platform_timers hd.hd_irq[1] = HPET_LEGACY_RTC; for (i = 2; i < nrtimers; timer++, i++) - hd.hd_irq[i] = (timer->hpet_config & Tn_INT_ROUTE_CNF_MASK) >> + hd.hd_irq[i] = (readl(&timer->hpet_config) & Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT; hpet_alloc(&hd); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/i386_ksyms.c linux-2.6.22.19-g-v/arch/i386/kernel/i386_ksyms.c --- linux-2.6.22.19/arch/i386/kernel/i386_ksyms.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/i386_ksyms.c 2008-03-04 08:55:59.000000000 +0100 @@ -2,12 +2,16 @@ #include #include +EXPORT_SYMBOL_GPL(cpu_gdt_table); + EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); EXPORT_SYMBOL(__down_failed_trylock); EXPORT_SYMBOL(__up_wakeup); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); +EXPORT_SYMBOL(csum_partial_copy_generic_to_user); +EXPORT_SYMBOL(csum_partial_copy_generic_from_user); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/i8259.c linux-2.6.22.19-g-v/arch/i386/kernel/i8259.c --- linux-2.6.22.19/arch/i386/kernel/i8259.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/i8259.c 2008-03-04 08:55:59.000000000 +0100 @@ -350,7 +350,7 @@ static irqreturn_t math_error_irq(int cp * New motherboards sometimes make IRQ 13 be a PCI interrupt, * so allow interrupt sharing. */ -static struct irqaction fpu_irq = { math_error_irq, 0, CPU_MASK_NONE, "fpu", NULL, NULL }; +static struct irqaction fpu_irq = { math_error_irq, 0, CPU_MASK_NONE, "fpu", NULL, NULL, 0, NULL }; void __init init_ISA_irqs (void) { diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/init_task.c linux-2.6.22.19-g-v/arch/i386/kernel/init_task.c --- linux-2.6.22.19/arch/i386/kernel/init_task.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/init_task.c 2008-03-04 08:55:59.000000000 +0100 @@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task); * per-CPU TSS segments. Threads are completely 'soft' on Linux, * no more per-task TSS's. */ -DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; +struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS }; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/io_apic.c linux-2.6.22.19-g-v/arch/i386/kernel/io_apic.c --- linux-2.6.22.19/arch/i386/kernel/io_apic.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/io_apic.c 2008-03-04 08:55:59.000000000 +0100 @@ -357,8 +357,8 @@ static void set_ioapic_affinity_irq(unsi # define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) # define Dprintk(x...) do { TDprintk(x); } while (0) # else -# define TDprintk(x...) -# define Dprintk(x...) +# define TDprintk(x...) do {} while (0) +# define Dprintk(x...) do {} while (0) # endif #define IRQBALANCE_CHECK_ARCH -999 diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/ioport.c linux-2.6.22.19-g-v/arch/i386/kernel/ioport.c --- linux-2.6.22.19/arch/i386/kernel/ioport.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/ioport.c 2008-03-04 08:55:59.000000000 +0100 @@ -16,6 +16,7 @@ #include #include #include +#include /* 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) @@ -64,9 +65,16 @@ asmlinkage long sys_ioperm(unsigned long 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(), @@ -89,7 +97,7 @@ asmlinkage long sys_ioperm(unsigned long * because the ->io_bitmap_max value must match the bitmap * contents: */ - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); @@ -143,8 +151,13 @@ asmlinkage long sys_iopl(unsigned long u 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 } t->iopl = level << 12; regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/irq.c linux-2.6.22.19-g-v/arch/i386/kernel/irq.c --- linux-2.6.22.19/arch/i386/kernel/irq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/irq.c 2008-03-04 08:55:59.000000000 +0100 @@ -117,7 +117,7 @@ fastcall unsigned int do_IRQ(struct pt_r int arg1, arg2, ebx; /* build the stack frame on the IRQ stack */ - isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2; irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_esp = current_stack_pointer; @@ -154,10 +154,10 @@ fastcall unsigned int do_IRQ(struct pt_r * gcc's 3.0 and earlier don't handle that correctly. */ static char softirq_stack[NR_CPUS * THREAD_SIZE] - __attribute__((__aligned__(THREAD_SIZE))); + __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned"))); static char hardirq_stack[NR_CPUS * THREAD_SIZE] - __attribute__((__aligned__(THREAD_SIZE))); + __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned"))); /* * allocate per-cpu stacks for hardirq and for softirq processing @@ -217,7 +217,7 @@ asmlinkage void do_softirq(void) irqctx->tinfo.previous_esp = current_stack_pointer; /* build the stack frame on the softirq stack */ - isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2; asm volatile( " xchgl %%ebx,%%esp \n" diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/kprobes.c linux-2.6.22.19-g-v/arch/i386/kernel/kprobes.c --- linux-2.6.22.19/arch/i386/kernel/kprobes.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/kprobes.c 2008-03-04 08:55:59.000000000 +0100 @@ -48,9 +48,24 @@ static __always_inline void set_jmp_op(v char op; long raddr; } __attribute__((packed)) *jop; - jop = (struct __arch_jmp_op *)from; + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + + jop = (struct __arch_jmp_op *)(from + __KERNEL_TEXT_OFFSET); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + jop->raddr = (long)(to) - ((long)(from) + 5); jop->op = RELATIVEJUMP_INSTRUCTION; + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + } /* @@ -152,12 +167,26 @@ static int __kprobes is_IF_modifier(kpro int __kprobes arch_prepare_kprobe(struct kprobe *p) { + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + /* insn: must be on special executable page on i386. */ p->ainsn.insn = get_insn_slot(); if (!p->ainsn.insn) return -ENOMEM; - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + memcpy(p->ainsn.insn, p->addr + __KERNEL_TEXT_OFFSET, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + p->opcode = *p->addr; if (can_boost(p->addr)) { p->ainsn.boostable = 0; @@ -222,7 +251,7 @@ static void __kprobes prepare_singlestep if (p->opcode == BREAKPOINT_INSTRUCTION) regs->eip = (unsigned long)p->addr; else - regs->eip = (unsigned long)p->ainsn.insn; + regs->eip = (unsigned long)p->ainsn.insn - __KERNEL_TEXT_OFFSET; } /* Called with kretprobe_lock held */ @@ -328,7 +357,7 @@ ss_probe: if (p->ainsn.boostable == 1 && !p->post_handler){ /* Boost up -- we can execute copied instructions directly */ reset_current_kprobe(); - regs->eip = (unsigned long)p->ainsn.insn; + regs->eip = (unsigned long)p->ainsn.insn - __KERNEL_TEXT_OFFSET; preempt_enable_no_resched(); return 1; } @@ -478,7 +507,7 @@ static void __kprobes resume_execution(s struct pt_regs *regs, struct kprobe_ctlblk *kcb) { unsigned long *tos = (unsigned long *)®s->esp; - unsigned long copy_eip = (unsigned long)p->ainsn.insn; + unsigned long copy_eip = (unsigned long)p->ainsn.insn - __KERNEL_TEXT_OFFSET; unsigned long orig_eip = (unsigned long)p->addr; regs->eflags &= ~TF_MASK; @@ -651,7 +680,7 @@ int __kprobes kprobe_exceptions_notify(s struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - if (args->regs && user_mode_vm(args->regs)) + if (args->regs && user_mode(args->regs)) return ret; switch (val) { diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/ldt.c linux-2.6.22.19-g-v/arch/i386/kernel/ldt.c --- linux-2.6.22.19/arch/i386/kernel/ldt.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/ldt.c 2008-03-04 08:55:59.000000000 +0100 @@ -58,7 +58,7 @@ static int alloc_ldt(mm_context_t *pc, i #ifdef CONFIG_SMP cpumask_t mask; preempt_disable(); - load_LDT(pc); + load_LDT_nolock(pc); mask = cpumask_of_cpu(smp_processor_id()); if (!cpus_equal(current->mm->cpu_vm_mask, mask)) smp_call_function(flush_ldt, NULL, 1, 1); @@ -102,6 +102,22 @@ int init_new_context(struct task_struct retval = copy_ldt(&mm->context, &old_mm->context); up(&old_mm->context.sem); } + + if (tsk == current) { + mm->context.vdso = ~0UL; + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + mm->context.user_cs_base = 0UL; + mm->context.user_cs_limit = ~0UL; + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) + cpus_clear(mm->context.cpu_user_cs_mask); +#endif + +#endif + + } + return retval; } @@ -212,6 +228,13 @@ static int write_ldt(void __user * ptr, } } +#ifdef CONFIG_PAX_SEGMEXEC + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) { + error = -EINVAL; + goto out_unlock; + } +#endif + entry_1 = LDT_entry_a(&ldt_info); entry_2 = LDT_entry_b(&ldt_info); if (oldmode) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/machine_kexec.c linux-2.6.22.19-g-v/arch/i386/kernel/machine_kexec.c --- linux-2.6.22.19/arch/i386/kernel/machine_kexec.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/machine_kexec.c 2008-03-04 08:55:59.000000000 +0100 @@ -29,25 +29,25 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED static u32 kexec_pte0[1024] PAGE_ALIGNED; static u32 kexec_pte1[1024] PAGE_ALIGNED; -static void set_idt(void *newidt, __u16 limit) +static void set_idt(struct desc_struct *newidt, __u16 limit) { struct Xgt_desc_struct curidt; /* ia32 supports unaliged loads & stores */ curidt.size = limit; - curidt.address = (unsigned long)newidt; + curidt.address = newidt; load_idt(&curidt); }; -static void set_gdt(void *newgdt, __u16 limit) +static void set_gdt(struct desc_struct *newgdt, __u16 limit) { struct Xgt_desc_struct curgdt; /* ia32 supports unaligned loads & stores */ curgdt.size = limit; - curgdt.address = (unsigned long)newgdt; + curgdt.address = newgdt; load_gdt(&curgdt); }; @@ -110,10 +110,10 @@ NORET_TYPE void machine_kexec(struct kim local_irq_disable(); control_page = page_address(image->control_code_page); - memcpy(control_page, relocate_kernel, PAGE_SIZE); + memcpy(control_page, relocate_kernel + __KERNEL_TEXT_OFFSET, PAGE_SIZE); page_list[PA_CONTROL_PAGE] = __pa(control_page); - page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; + page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel + __KERNEL_TEXT_OFFSET; page_list[PA_PGD] = __pa(kexec_pgd); page_list[VA_PGD] = (unsigned long)kexec_pgd; #ifdef CONFIG_X86_PAE diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/module.c linux-2.6.22.19-g-v/arch/i386/kernel/module.c --- linux-2.6.22.19/arch/i386/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/module.c 2008-03-04 08:55:59.000000000 +0100 @@ -23,6 +23,8 @@ #include #include +#include + #if 0 #define DEBUGP printk #else @@ -33,9 +35,30 @@ void *module_alloc(unsigned long size) { if (size == 0) return NULL; + +#ifdef CONFIG_PAX_KERNEXEC + return vmalloc(size); +#else return vmalloc_exec(size); +#endif + } +#ifdef CONFIG_PAX_KERNEXEC +void *module_alloc_exec(unsigned long size) +{ + struct vm_struct *area; + + if (size == 0) + return NULL; + + area = __get_vm_area(size, 0, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END); + if (area) + return area->addr; + + return NULL; +} +#endif /* Free memory returned from module_alloc */ void module_free(struct module *mod, void *module_region) @@ -45,6 +68,45 @@ void module_free(struct module *mod, voi table entries. */ } +#ifdef CONFIG_PAX_KERNEXEC +void module_free_exec(struct module *mod, void *module_region) +{ + struct vm_struct **p, *tmp; + + if (!module_region) + return; + + if ((PAGE_SIZE-1) & (unsigned long)module_region) { + printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region); + WARN_ON(1); + return; + } + + write_lock(&vmlist_lock); + for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) + if (tmp->addr == module_region) + break; + + if (tmp) { + unsigned long cr0; + + pax_open_kernel(cr0); + memset(tmp->addr, 0xCC, tmp->size); + pax_close_kernel(cr0); + + *p = tmp->next; + kfree(tmp); + } + write_unlock(&vmlist_lock); + + if (!tmp) { + printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n", + module_region); + WARN_ON(1); + } +} +#endif + /* We don't need anything special. */ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, @@ -63,14 +125,16 @@ int apply_relocate(Elf32_Shdr *sechdrs, unsigned int i; Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; Elf32_Sym *sym; - uint32_t *location; + uint32_t *plocation, location; DEBUGP("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; + plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; + location = (uint32_t)plocation; + if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR) + plocation = (void *)plocation + __KERNEL_TEXT_OFFSET; /* This is the symbol it is referring to. Note that all undefined symbols have been resolved. */ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr @@ -79,11 +143,11 @@ int apply_relocate(Elf32_Shdr *sechdrs, switch (ELF32_R_TYPE(rel[i].r_info)) { case R_386_32: /* We add the value into the location given */ - *location += sym->st_value; + *plocation += sym->st_value; break; case R_386_PC32: /* Add the value, subtract its postition */ - *location += sym->st_value - (uint32_t)location; + *plocation += sym->st_value - location; break; default: printk(KERN_ERR "module %s: Unknown relocation: %u\n", diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/paravirt.c linux-2.6.22.19-g-v/arch/i386/kernel/paravirt.c --- linux-2.6.22.19/arch/i386/kernel/paravirt.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/paravirt.c 2008-03-04 08:55:59.000000000 +0100 @@ -188,7 +188,7 @@ unsigned paravirt_patch_insns(void *site if (insn_len > len || start == NULL) insn_len = len; else - memcpy(site, start, insn_len); + memcpy(site, start + __KERNEL_TEXT_OFFSET, insn_len); return insn_len; } @@ -228,7 +228,7 @@ static int __init print_banner(void) } core_initcall(print_banner); -struct paravirt_ops paravirt_ops = { +struct paravirt_ops paravirt_ops __read_only = { .name = "bare hardware", .paravirt_enabled = 0, .kernel_rpl = 0, diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/process.c linux-2.6.22.19-g-v/arch/i386/kernel/process.c --- linux-2.6.22.19/arch/i386/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -68,15 +68,17 @@ EXPORT_SYMBOL(boot_option_idle_override) DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; EXPORT_PER_CPU_SYMBOL(current_task); +#ifdef CONFIG_SMP DEFINE_PER_CPU(int, cpu_number); EXPORT_PER_CPU_SYMBOL(cpu_number); +#endif /* * Return saved PC of a blocked thread. */ unsigned long thread_saved_pc(struct task_struct *tsk) { - return ((unsigned long *)tsk->thread.esp)[3]; + return tsk->thread.eip; } /* @@ -302,11 +304,13 @@ void show_regs(struct pt_regs * regs) unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; printk("\n"); - printk("Pid: %d, comm: %20s\n", current->pid, current->comm); - printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id()); + printk("Pid: %d[#%u], comm: %20s\n", + current->pid, current->xid, current->comm); + printk("EIP: %04x:[<%08lx>] CPU: %d\n", + 0xffff & regs->xcs,regs->eip, smp_processor_id()); print_symbol("EIP is at %s\n", regs->eip); - if (user_mode_vm(regs)) + if (user_mode(regs)) printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); printk(" EFLAGS: %08lx %s (%s %.*s)\n", regs->eflags, print_tainted(), init_utsname()->release, @@ -346,8 +350,8 @@ int kernel_thread(int (*fn)(void *), voi regs.ebx = (unsigned long) fn; regs.edx = (unsigned long) arg; - regs.xds = __USER_DS; - regs.xes = __USER_DS; + regs.xds = __KERNEL_DS; + regs.xes = __KERNEL_DS; regs.xfs = __KERNEL_PERCPU; regs.orig_eax = -1; regs.eip = (unsigned long) kernel_thread_helper; @@ -355,7 +359,8 @@ int kernel_thread(int (*fn)(void *), voi regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); @@ -369,7 +374,7 @@ void exit_thread(void) struct task_struct *tsk = current; struct thread_struct *t = &tsk->thread; int cpu = get_cpu(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; kfree(t->io_bitmap_ptr); t->io_bitmap_ptr = NULL; @@ -390,6 +395,7 @@ void flush_thread(void) { struct task_struct *tsk = current; + __asm__("mov %0,%%gs\n" : : "r" (0) : "memory"); memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); clear_tsk_thread_flag(tsk, TIF_DEBUG); @@ -423,7 +429,7 @@ int copy_thread(int nr, unsigned long cl struct task_struct *tsk; int err; - childregs = task_pt_regs(p); + childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8; *childregs = *regs; childregs->eax = 0; childregs->esp = esp; @@ -465,6 +471,11 @@ int copy_thread(int nr, unsigned long cl if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) goto out; +#ifdef CONFIG_PAX_SEGMEXEC + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE)) + goto out; +#endif + desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; desc->a = LDT_entry_a(&info); desc->b = LDT_entry_b(&info); @@ -644,7 +655,7 @@ struct task_struct fastcall * __switch_t struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; int cpu = smp_processor_id(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ @@ -672,6 +683,11 @@ struct task_struct fastcall * __switch_t */ savesegment(gs, prev->gs); +#ifdef CONFIG_PAX_MEMORY_UDEREF + if (!segment_eq(task_thread_info(prev_p)->addr_limit, task_thread_info(next_p)->addr_limit)) + __set_fs(task_thread_info(next_p)->addr_limit, cpu); +#endif + /* * Load the per-thread Thread-Local Storage descriptor. */ @@ -838,6 +854,12 @@ asmlinkage int sys_set_thread_area(struc if (copy_from_user(&info, u_info, sizeof(info))) return -EFAULT; + +#ifdef CONFIG_PAX_SEGMEXEC + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE)) + return -EINVAL; +#endif + idx = info.entry_number; /* @@ -926,9 +948,28 @@ asmlinkage int sys_get_thread_area(struc return 0; } -unsigned long arch_align_stack(unsigned long sp) +#ifdef CONFIG_PAX_RANDKSTACK +asmlinkage void pax_randomize_kstack(void) { - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() % 8192; - return sp & ~0xf; + struct tss_struct *tss; + unsigned long time; + + if (!randomize_va_space) + return; + + tss = init_tss + smp_processor_id(); + rdtscl(time); + + /* P4 seems to return a 0 LSB, ignore it */ +#ifdef CONFIG_MPENTIUM4 + time &= 0x1EUL; + time <<= 2; +#else + time &= 0xFUL; + time <<= 3; +#endif + + tss->x86_tss.esp0 ^= time; + current->thread.esp0 = tss->x86_tss.esp0; } +#endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/ptrace.c linux-2.6.22.19-g-v/arch/i386/kernel/ptrace.c --- linux-2.6.22.19/arch/i386/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -191,6 +191,9 @@ static inline int is_setting_trap_flag(s unsigned char opcode[15]; unsigned long addr = convert_eip_to_linear(child, regs); + if (addr == -EINVAL) + return 0; + copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); for (i = 0; i < copied; i++) { switch (opcode[i]) { @@ -342,6 +345,11 @@ ptrace_set_thread_area(struct task_struc if (copy_from_user(&info, user_desc, sizeof(info))) return -EFAULT; +#ifdef CONFIG_PAX_SEGMEXEC + if ((child->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE)) + return -EINVAL; +#endif + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) return -EINVAL; @@ -432,6 +440,17 @@ long arch_ptrace(struct task_struct *chi 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 /* Sanity-check data. Take one half-byte at once with * check = (val >> (16 + 4*i)) & 0xf. It contains the @@ -648,7 +667,7 @@ void send_sigtrap(struct task_struct *ts info.si_code = TRAP_BRKPT; /* User-mode eip? */ - info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL; + info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL; /* Send us the fakey SIGTRAP */ force_sig_info(SIGTRAP, &info, tsk); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/reboot.c linux-2.6.22.19-g-v/arch/i386/kernel/reboot.c --- linux-2.6.22.19/arch/i386/kernel/reboot.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/reboot.c 2008-03-04 08:55:59.000000000 +0100 @@ -26,7 +26,7 @@ void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); -static int reboot_mode; +static unsigned short reboot_mode; static int reboot_thru_bios; #ifdef CONFIG_SMP @@ -129,7 +129,7 @@ static struct dmi_system_id __initdata r DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), }, }, - { } + { NULL, NULL, {{0, NULL}}, NULL} }; static int __init reboot_init(void) @@ -147,18 +147,18 @@ core_initcall(reboot_init); 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 -real_mode_gdt_entries [3] = +static struct desc_struct +real_mode_gdt_entries [3] __read_only = { - 0x0000000000000000ULL, /* Null descriptor */ - 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ - 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ + {0x00000000, 0x00000000}, /* Null descriptor */ + {0x0000ffff, 0x00009b00}, /* 16-bit real-mode 64k code at 0x00000000 */ + {0x0100ffff, 0x00009300} /* 16-bit real-mode 64k data at 0x00000100 */ }; -static struct Xgt_desc_struct -real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries }, -real_mode_idt = { 0x3ff, 0 }, -no_idt = { 0, 0 }; +static const struct Xgt_desc_struct +real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (struct desc_struct *)__pa(real_mode_gdt_entries), 0 }, +real_mode_idt = { 0x3ff, NULL, 0 }, +no_idt = { 0, NULL, 0 }; /* This is 16-bit protected mode code to disable paging and the cache, @@ -180,7 +180,7 @@ no_idt = { 0, 0 }; More could be done here to set up the registers as if a CPU reset had occurred; hopefully real BIOSs don't assume much. */ -static unsigned char real_mode_switch [] = +static const unsigned char real_mode_switch [] = { 0x66, 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */ 0x66, 0x83, 0xe0, 0x11, /* andl $0x00000011,%eax */ @@ -194,7 +194,7 @@ static unsigned char real_mode_switch [] 0x24, 0x10, /* f: andb $0x10,al */ 0x66, 0x0f, 0x22, 0xc0 /* movl %eax,%cr0 */ }; -static unsigned char jump_to_bios [] = +static const unsigned char jump_to_bios [] = { 0xea, 0x00, 0x00, 0xff, 0xff /* ljmp $0xffff,$0x0000 */ }; @@ -204,8 +204,13 @@ static unsigned char jump_to_bios [] = * specified by the code and length parameters. * We assume that length will aways be less that 100! */ -void machine_real_restart(unsigned char *code, int length) +void machine_real_restart(const unsigned char *code, unsigned int length) { + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + local_irq_disable(); /* Write zero to CMOS register number 0x0f, which the BIOS POST @@ -226,8 +231,16 @@ void machine_real_restart(unsigned char from the kernel segment. This assumes the kernel segment starts at virtual address PAGE_OFFSET. */ - memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, - sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS); +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif /* * Use `swapper_pg_dir' as our page directory. @@ -240,7 +253,7 @@ void machine_real_restart(unsigned char REBOOT.COM programs, and the previous reset routine did this too. */ - *((unsigned short *)0x472) = reboot_mode; + *(unsigned short *)(__va(0x472)) = reboot_mode; /* For the switch to real mode, copy some code to low memory. It has to be in the first 64k because it is running in 16-bit mode, and it @@ -248,9 +261,8 @@ void machine_real_restart(unsigned char off paging. Copy it near the end of the first page, out of the way of BIOS variables. */ - memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100), - real_mode_switch, sizeof (real_mode_switch)); - memcpy ((void *) (0x1000 - 100), code, length); + memcpy(__va(0x1000 - sizeof (real_mode_switch) - 100), real_mode_switch, sizeof (real_mode_switch)); + memcpy(__va(0x1000 - 100), code, length); /* Set up the IDT for real mode. */ @@ -336,7 +348,7 @@ static void native_machine_emergency_res __asm__ __volatile__("int3"); } /* rebooting needs to touch the page at absolute addr 0 */ - *((unsigned short *)__va(0x472)) = reboot_mode; + *(unsigned short *)(__va(0x472)) = reboot_mode; for (;;) { mach_reboot_fixups(); /* for board specific fixups */ mach_reboot(); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/setup.c linux-2.6.22.19-g-v/arch/i386/kernel/setup.c --- linux-2.6.22.19/arch/i386/kernel/setup.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/setup.c 2008-03-04 08:55:59.000000000 +0100 @@ -82,7 +82,11 @@ struct cpuinfo_x86 new_cpu_data __cpuini struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; EXPORT_SYMBOL(boot_cpu_data); +#ifdef CONFIG_X86_PAE +unsigned long mmu_cr4_features = X86_CR4_PAE; +#else unsigned long mmu_cr4_features; +#endif /* for MCA, but anyone else can use it if they want */ unsigned int machine_id; @@ -404,8 +408,8 @@ void __init setup_bootmem_allocator(void * the (very unlikely) case of us accidentally initializing the * bootmem allocator with an invalid RAM area. */ - reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) + - bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text)); + reserve_bootmem(LOAD_PHYSICAL_ADDR, (PFN_PHYS(min_low_pfn) + + bootmap_size + PAGE_SIZE-1) - LOAD_PHYSICAL_ADDR); /* * reserve physical page 0 - it's a special BIOS page on many boxes, @@ -559,14 +563,14 @@ void __init setup_arch(char **cmdline_p) if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; + init_mm.start_code = (unsigned long) _text + __KERNEL_TEXT_OFFSET; + init_mm.end_code = (unsigned long) _etext + __KERNEL_TEXT_OFFSET; init_mm.end_data = (unsigned long) _edata; init_mm.brk = init_pg_tables_end + PAGE_OFFSET; - code_resource.start = virt_to_phys(_text); - code_resource.end = virt_to_phys(_etext)-1; - data_resource.start = virt_to_phys(_etext); + code_resource.start = virt_to_phys(_text + __KERNEL_TEXT_OFFSET); + code_resource.end = virt_to_phys(_etext + __KERNEL_TEXT_OFFSET)-1; + data_resource.start = virt_to_phys(_data); data_resource.end = virt_to_phys(_edata)-1; parse_early_param(); @@ -658,3 +662,24 @@ void __init setup_arch(char **cmdline_p) #endif #endif } + +unsigned long __per_cpu_offset[NR_CPUS] __read_only; + +EXPORT_SYMBOL(__per_cpu_offset); + +void __init setup_per_cpu_areas(void) +{ + unsigned long size, i; + char *ptr; + unsigned long nr_possible_cpus = num_possible_cpus(); + + /* Copy section for each CPU (we discard the original) */ + size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE); + ptr = alloc_bootmem_pages(size * nr_possible_cpus); + + for_each_possible_cpu(i) { + __per_cpu_offset[i] = (unsigned long)ptr; + memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); + ptr += size; + } +} diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/signal.c linux-2.6.22.19-g-v/arch/i386/kernel/signal.c --- linux-2.6.22.19/arch/i386/kernel/signal.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/signal.c 2008-03-04 08:55:59.000000000 +0100 @@ -350,9 +350,9 @@ static int setup_frame(int sig, struct k } if (current->binfmt->hasvdso) - restorer = (void *)VDSO_SYM(&__kernel_sigreturn); + restorer = (void __user *)VDSO_SYM(&__kernel_sigreturn); else - restorer = (void *)&frame->retcode; + restorer = (void __user *)&frame->retcode; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; @@ -448,7 +448,8 @@ static int setup_rt_frame(int sig, struc goto give_sigsegv; /* Set up to return from userspace. */ - restorer = (void *)VDSO_SYM(&__kernel_rt_sigreturn); + + restorer = (void __user *)VDSO_SYM(&__kernel_rt_sigreturn); if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(restorer, &frame->pretcode); @@ -581,7 +582,7 @@ static void fastcall do_signal(struct pt * before reaching here, so testing against kernel * CS suffices. */ - if (!user_mode(regs)) + if (!user_mode_novm(regs)) return; if (test_thread_flag(TIF_RESTORE_SIGMASK)) diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/smp.c linux-2.6.22.19-g-v/arch/i386/kernel/smp.c --- linux-2.6.22.19/arch/i386/kernel/smp.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/smp.c 2008-03-04 08:55:59.000000000 +0100 @@ -103,7 +103,7 @@ * about nothing of note with C stepping upwards. */ -DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, }; +DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, {0} }; /* * the following functions deal with sending IPIs between CPUs. diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/smpboot.c linux-2.6.22.19-g-v/arch/i386/kernel/smpboot.c --- linux-2.6.22.19/arch/i386/kernel/smpboot.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/smpboot.c 2008-03-04 08:55:59.000000000 +0100 @@ -118,7 +118,7 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 }; * has made sure it's suitably aligned. */ -static unsigned long __devinit setup_trampoline(void) +static unsigned long __cpuinit setup_trampoline(void) { memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data); return virt_to_phys(trampoline_base); @@ -773,6 +773,10 @@ static int __cpuinit do_boot_cpu(int api unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + /* * Save current MTRR state in case it was changed since early boot * (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: @@ -789,7 +793,16 @@ static int __cpuinit do_boot_cpu(int api init_gdt(cpu); per_cpu(current_task, cpu) = idle; - early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + early_gdt_descr.address = get_cpu_gdt_table(cpu); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif idle->thread.eip = (unsigned long) start_secondary; /* start_eip had better be page-aligned! */ diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/smpcommon.c linux-2.6.22.19-g-v/arch/i386/kernel/smpcommon.c --- linux-2.6.22.19/arch/i386/kernel/smpcommon.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/smpcommon.c 2008-03-04 08:55:59.000000000 +0100 @@ -3,6 +3,7 @@ */ #include #include +#include DEFINE_PER_CPU(unsigned long, this_cpu_off); EXPORT_PER_CPU_SYMBOL(this_cpu_off); @@ -14,10 +15,29 @@ __cpuinit void init_gdt(int cpu) { struct desc_struct *gdt = get_cpu_gdt_table(cpu); - pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, - (u32 *)&gdt[GDT_ENTRY_PERCPU].b, - __per_cpu_offset[cpu], 0xFFFFF, - 0x80 | DESCTYPE_S | 0x2, 0x8); +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; + + pax_open_kernel(cr0); +#endif + + if (cpu) + memcpy(gdt, cpu_gdt_table, GDT_SIZE); + + if (PERCPU_ENOUGH_ROOM <= 64*1024*1024) + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (__u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], PERCPU_ENOUGH_ROOM-1, + 0x80 | DESCTYPE_S | 0x3, 0x4); + else + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (__u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], ((PERCPU_ENOUGH_ROOM-1) >> PAGE_SHIFT), + 0x80 | DESCTYPE_S | 0x3, 0xC); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; per_cpu(cpu_number, cpu) = cpu; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/sys_i386.c linux-2.6.22.19-g-v/arch/i386/kernel/sys_i386.c --- linux-2.6.22.19/arch/i386/kernel/sys_i386.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/sys_i386.c 2008-03-04 08:55:59.000000000 +0100 @@ -40,6 +40,21 @@ asmlinkage int sys_pipe(unsigned long __ return error; } +int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) +{ + unsigned long task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif + + if (len > task_size || addr > task_size - len) + return -EINVAL; + + return 0; +} + asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) @@ -99,6 +114,205 @@ out: return err; } +unsigned long +arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start_addr, task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif + + if (len > task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) + return addr; + +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (task_size - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + if (len > mm->cached_hole_size) { + start_addr = addr = mm->free_area_cache; + } else { + start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; + } + +#ifdef CONFIG_PAX_PAGEEXEC + if (!nx_enabled && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) { + start_addr = 0x00110000UL; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + start_addr += mm->delta_mmap & 0x03FFF000UL; +#endif + + if (mm->start_brk <= start_addr && start_addr < mm->mmap_base) + start_addr = addr = mm->mmap_base; + else + addr = start_addr; + } +#endif + +full_search: + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (task_size - len < addr) { + /* + * Start a new search - just in case we missed + * some holes. + */ + if (start_addr != mm->mmap_base) { + start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; + goto full_search; + } + return -ENOMEM; + } + if (!vma || addr + len <= vma->vm_start) { + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } + if (addr + mm->cached_hole_size < vma->vm_start) + mm->cached_hole_size = vma->vm_start - addr; + addr = vma->vm_end; + if (mm->start_brk <= addr && addr < mm->mmap_base) { + start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; + goto full_search; + } + } +} + +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) +{ + struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; + unsigned long base = mm->mmap_base, addr = addr0, task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif + + /* requested length too big for entire address space */ + if (len > task_size) + return -ENOMEM; + + if (flags & MAP_FIXED) + return addr; + +#ifdef CONFIG_PAX_PAGEEXEC + if (!nx_enabled && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE)) + goto bottomup; +#endif + +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (task_size - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + + /* check if free_area_cache is useful for us */ + if (len <= mm->cached_hole_size) { + mm->cached_hole_size = 0; + mm->free_area_cache = mm->mmap_base; + } + + /* either no address requested or can't fit in requested address hole */ + addr = mm->free_area_cache; + + /* make sure it can fit in the remaining address space */ + if (addr > len) { + vma = find_vma(mm, addr-len); + if (!vma || addr <= vma->vm_start) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr-len); + } + + if (mm->mmap_base < len) + goto bottomup; + + addr = mm->mmap_base-len; + + do { + /* + * Lookup failure means no vma is above this address, + * else if new region fits below vma->vm_start, + * return with success: + */ + vma = find_vma(mm, addr); + if (!vma || addr+len <= vma->vm_start) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + + /* remember the largest hole we saw so far */ + if (addr + mm->cached_hole_size < vma->vm_start) + mm->cached_hole_size = vma->vm_start - addr; + + /* try just below the current vma->vm_start */ + addr = vma->vm_start-len; + } while (len < vma->vm_start); + +bottomup: + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE; + else +#endif + + mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + + mm->free_area_cache = mm->mmap_base; + mm->cached_hole_size = ~0UL; + addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); + /* + * Restore the topdown base: + */ + mm->mmap_base = base; + mm->free_area_cache = base; + mm->cached_hole_size = ~0UL; + + return addr; +} struct sel_arg_struct { unsigned long n; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/syscall_table.S linux-2.6.22.19-g-v/arch/i386/kernel/syscall_table.S --- linux-2.6.22.19/arch/i386/kernel/syscall_table.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/syscall_table.S 2008-03-04 08:55:59.000000000 +0100 @@ -1,3 +1,4 @@ +.section .rodata,"a",@progbits ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ .long sys_exit @@ -272,7 +273,7 @@ ENTRY(sys_call_table) .long sys_tgkill /* 270 */ .long sys_utimes .long sys_fadvise64_64 - .long sys_ni_syscall /* sys_vserver */ + .long sys_vserver .long sys_mbind .long sys_get_mempolicy .long sys_set_mempolicy diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/sysenter.c linux-2.6.22.19-g-v/arch/i386/kernel/sysenter.c --- linux-2.6.22.19/arch/i386/kernel/sysenter.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/sysenter.c 2008-03-04 08:55:59.000000000 +0100 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -176,7 +177,7 @@ static __init void relocate_vdso(Elf32_E void enable_sep_cpu(void) { int cpu = get_cpu(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = init_tss + cpu; if (!boot_cpu_has(X86_FEATURE_SEP)) { put_cpu(); @@ -199,7 +200,7 @@ static int __init gate_vma_init(void) gate_vma.vm_start = FIXADDR_USER_START; gate_vma.vm_end = FIXADDR_USER_END; gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; - gate_vma.vm_page_prot = __P101; + gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); /* * Make sure the vDSO gets into every core dump. * Dumping its contents makes post-mortem fully interpretable later @@ -282,7 +283,7 @@ int arch_setup_additional_pages(struct l if (compat) addr = VDSO_HIGH_BASE; else { - addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); + addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, MAP_EXECUTABLE); if (IS_ERR_VALUE(addr)) { ret = addr; goto up_fail; @@ -307,7 +308,7 @@ int arch_setup_additional_pages(struct l goto up_fail; } - current->mm->context.vdso = (void *)addr; + current->mm->context.vdso = addr; current_thread_info()->sysenter_return = (void *)VDSO_SYM(&SYSENTER_RETURN); @@ -319,8 +320,14 @@ int arch_setup_additional_pages(struct l const char *arch_vma_name(struct vm_area_struct *vma) { - if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) + if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso) + return "[vdso]"; + +#ifdef CONFIG_PAX_SEGMEXEC + if (vma->vm_mm && vma->vm_mirror && vma->vm_mirror->vm_start == vma->vm_mm->context.vdso) return "[vdso]"; +#endif + return NULL; } @@ -329,7 +336,7 @@ struct vm_area_struct *get_gate_vma(stru struct mm_struct *mm = tsk->mm; /* Check to see if this task was created in compat vdso mode */ - if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE) + if (mm && mm->context.vdso == VDSO_HIGH_BASE) return &gate_vma; return NULL; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/time.c linux-2.6.22.19-g-v/arch/i386/kernel/time.c --- linux-2.6.22.19/arch/i386/kernel/time.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/time.c 2008-03-04 08:55:59.000000000 +0100 @@ -132,20 +132,30 @@ unsigned long profile_pc(struct pt_regs if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs) && in_lock_functions(pc)) { #ifdef CONFIG_FRAME_POINTER - return *(unsigned long *)(regs->ebp + 4); + return *(unsigned long *)(regs->ebp + 4) + __KERNEL_TEXT_OFFSET; #else unsigned long *sp = (unsigned long *)®s->esp; /* Return address is either directly at stack pointer or above a saved eflags. Eflags has bits 22-31 zero, kernel addresses don't. */ + +#ifdef CONFIG_PAX_KERNEXEC + return sp[0] + __KERNEL_TEXT_OFFSET; +#else if (sp[0] >> 22) return sp[0]; if (sp[1] >> 22) return sp[1]; #endif + +#endif } #endif + + if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs)) + pc += __KERNEL_TEXT_OFFSET; + return pc; } EXPORT_SYMBOL(profile_pc); diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/traps.c linux-2.6.22.19-g-v/arch/i386/kernel/traps.c --- linux-2.6.22.19/arch/i386/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef CONFIG_EISA #include @@ -56,6 +57,8 @@ #include #include +#include +#include #include "mach_traps.h" @@ -66,12 +69,7 @@ asmlinkage int system_call(void); /* 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); @@ -283,7 +281,7 @@ void show_registers(struct pt_regs *regs esp = (unsigned long) (®s->esp); savesegment(ss, ss); savesegment(gs, gs); - if (user_mode_vm(regs)) { + if (user_mode(regs)) { in_kernel = 0; esp = regs->esp; ss = regs->xss & 0xffff; @@ -303,8 +301,8 @@ void show_registers(struct pt_regs *regs regs->esi, regs->edi, regs->ebp, esp); printk(KERN_EMERG "ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, regs->xfs & 0xffff, gs, ss); - printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", - TASK_COMM_LEN, current->comm, current->pid, + printk(KERN_EMERG "Process %.*s (pid: %d[#%u], ti=%p task=%p task.ti=%p)", + TASK_COMM_LEN, current->comm, current->pid, current->xid, current_thread_info(), current, task_thread_info(current)); /* * When in-kernel, we also print out the stack and code at the @@ -315,17 +313,18 @@ void show_registers(struct pt_regs *regs unsigned int code_prologue = code_bytes * 43 / 64; unsigned int code_len = code_bytes; unsigned char c; + unsigned long cs_base = get_desc_base(&get_cpu_gdt_table(smp_processor_id())[(0xffff & regs->xcs) >> 3]); printk("\n" KERN_EMERG "Stack: "); show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG); printk(KERN_EMERG "Code: "); - eip = (u8 *)regs->eip - code_prologue; + eip = (u8 *)regs->eip - code_prologue + cs_base; if (eip < (u8 *)PAGE_OFFSET || probe_kernel_address(eip, c)) { /* try starting at EIP */ - eip = (u8 *)regs->eip; + eip = (u8 *)regs->eip + cs_base; code_len = code_len - code_prologue + 1; } for (i = 0; i < code_len; i++, eip++) { @@ -334,7 +333,7 @@ void show_registers(struct pt_regs *regs printk(" Bad EIP value."); break; } - if (eip == (u8 *)regs->eip) + if (eip == (u8 *)regs->eip + cs_base) printk("<%02x> ", c); else printk("%02x ", c); @@ -347,6 +346,7 @@ int is_valid_bugaddr(unsigned long eip) { unsigned short ud2; + eip += __KERNEL_TEXT_OFFSET; if (eip < PAGE_OFFSET) return 0; if (probe_kernel_address((unsigned short *)eip, ud2)) @@ -375,6 +375,8 @@ void die(const char * str, struct pt_reg oops_enter(); + vxh_throw_oops(); + if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); spin_lock_irqsave(&die.lock, flags); @@ -412,9 +414,9 @@ void die(const char * str, struct pt_reg if (nl) printk("\n"); if (notify_die(DIE_OOPS, str, regs, err, - current->thread.trap_no, SIGSEGV) != - NOTIFY_STOP) { + current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) { show_registers(regs); + vxh_dump_history(); /* Executive summary in case the oops scrolled away */ esp = (unsigned long) (®s->esp); savesegment(ss, ss); @@ -453,7 +455,7 @@ void die(const char * str, struct pt_reg static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) { - if (!user_mode_vm(regs)) + if (!user_mode(regs)) die(str, regs, err); } @@ -469,7 +471,7 @@ static void __kprobes do_trap(int trapnr goto trap_signal; } - if (!user_mode(regs)) + if (!user_mode_novm(regs)) goto kernel_trap; trap_signal: { @@ -574,7 +576,7 @@ fastcall void __kprobes do_general_prote long error_code) { int cpu = get_cpu(); - struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct tss_struct *tss = &init_tss[cpu]; struct thread_struct *thread = ¤t->thread; /* @@ -607,9 +609,25 @@ fastcall void __kprobes do_general_prote if (regs->eflags & VM_MASK) goto gp_in_vm86; - if (!user_mode(regs)) + if (!user_mode_novm(regs)) goto gp_in_kernel; +#ifdef CONFIG_PAX_PAGEEXEC + if (!nx_enabled && current->mm && (current->mm->pax_flags & MF_PAX_PAGEEXEC)) { + struct mm_struct *mm = current->mm; + unsigned long limit; + + down_write(&mm->mmap_sem); + limit = mm->context.user_cs_limit; + if (limit < TASK_SIZE) { + track_exec_limit(mm, limit, TASK_SIZE, VM_EXEC); + up_write(&mm->mmap_sem); + return; + } + up_write(&mm->mmap_sem); + } +#endif + current->thread.error_code = error_code; current->thread.trap_no = 13; force_sig(SIGSEGV, current); @@ -627,6 +645,13 @@ gp_in_kernel: if (notify_die(DIE_GPF, "general protection fault", regs, error_code, 13, SIGSEGV) == NOTIFY_STOP) return; + +#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); } } @@ -708,7 +733,7 @@ void __kprobes die_nmi(struct pt_regs *r /* If we are in kernel we are probably nested up pretty bad * and might aswell get out now while we still can. */ - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { current->thread.trap_no = 2; crash_kexec(regs); } @@ -840,7 +865,7 @@ fastcall void __kprobes do_debug(struct * check for kernel mode by just checking the CPL * of CS. */ - if (!user_mode(regs)) + if (!user_mode_novm(regs)) goto clear_TF_reenable; } @@ -1018,18 +1043,14 @@ fastcall void do_spurious_interrupt_bug( fastcall unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) { - struct desc_struct *gdt = __get_cpu_var(gdt_page).gdt; unsigned long base = (kesp - uesp) & -THREAD_SIZE; unsigned long new_kesp = kesp - base; unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT; - __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS]; + __u32 a, b; + /* Set up base for espfix segment */ - desc &= 0x00f0ff0000000000ULL; - desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) | - ((((__u64)base) << 32) & 0xff00000000000000ULL) | - ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) | - (lim_pages & 0xffff); - *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc; + pack_descriptor(&a, &b, base, lim_pages, 0x93, 0xC); + write_gdt_entry(get_cpu_gdt_table(smp_processor_id()), GDT_ENTRY_ESPFIX_SS, a, b); return new_kesp; } @@ -1077,7 +1098,7 @@ void __init trap_init_f00f_bug(void) * Update the IDT descriptor and reload the IDT so that * it uses the read-only mapped virtual address. */ - idt_descr.address = fix_to_virt(FIX_F00F_IDT); + idt_descr.address = (struct desc_struct *)fix_to_virt(FIX_F00F_IDT); load_idt(&idt_descr); } #endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/tsc.c linux-2.6.22.19-g-v/arch/i386/kernel/tsc.c --- linux-2.6.22.19/arch/i386/kernel/tsc.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/tsc.c 2008-03-04 08:55:59.000000000 +0100 @@ -307,7 +307,7 @@ static struct dmi_system_id __initdata b DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), }, }, - {} + { NULL, NULL, {{0, NULL}}, NULL} }; /* diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/vm86.c linux-2.6.22.19-g-v/arch/i386/kernel/vm86.c --- linux-2.6.22.19/arch/i386/kernel/vm86.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/vm86.c 2008-03-04 08:55:59.000000000 +0100 @@ -148,7 +148,7 @@ struct pt_regs * fastcall save_v86_state do_exit(SIGSEGV); } - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); current->thread.esp0 = current->thread.saved_esp0; current->thread.sysenter_cs = __KERNEL_CS; load_esp0(tss, ¤t->thread); @@ -324,7 +324,7 @@ static void do_sys_vm86(struct kernel_vm tsk->thread.saved_fs = info->regs32->xfs; savesegment(gs, tsk->thread.saved_gs); - tss = &per_cpu(init_tss, get_cpu()); + tss = init_tss + get_cpu(); tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; if (cpu_has_sep) tsk->thread.sysenter_cs = 0; diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/vmi.c linux-2.6.22.19-g-v/arch/i386/kernel/vmi.c --- linux-2.6.22.19/arch/i386/kernel/vmi.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/vmi.c 2008-03-04 08:55:59.000000000 +0100 @@ -96,18 +96,43 @@ static unsigned patch_internal(int call, { u64 reloc; struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc; + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + reloc = call_vrom_long_func(vmi_rom, get_reloc, call); switch(rel->type) { case VMI_RELOCATION_CALL_REL: BUG_ON(len < 5); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + *(char *)insns = MNEM_CALL; patch_offset(insns, rel->eip); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + return 5; case VMI_RELOCATION_JUMP_REL: BUG_ON(len < 5); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + *(char *)insns = MNEM_JMP; patch_offset(insns, rel->eip); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + return 5; case VMI_RELOCATION_NOP: @@ -485,14 +510,14 @@ static void vmi_set_pud(pud_t *pudp, pud static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - const pte_t pte = { 0 }; + const pte_t pte = __pte(0ULL); vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); } static void vmi_pmd_clear(pmd_t *pmd) { - const pte_t pte = { 0 }; + const pte_t pte = __pte(0ULL); vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD); vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD); } @@ -521,8 +546,8 @@ vmi_startup_ipi_hook(int phys_apicid, un ap.ss = __KERNEL_DS; ap.esp = (unsigned long) start_esp; - ap.ds = __USER_DS; - ap.es = __USER_DS; + ap.ds = __KERNEL_DS; + ap.es = __KERNEL_DS; ap.fs = __KERNEL_PERCPU; ap.gs = 0; @@ -719,12 +744,20 @@ static inline int __init activate_vmi(vo u64 reloc; const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + if (call_vrom_func(vmi_rom, vmi_init) != 0) { printk(KERN_ERR "VMI ROM failed to initialize!"); return 0; } savesegment(cs, kernel_cs); +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + paravirt_ops.paravirt_enabled = 1; paravirt_ops.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK; @@ -903,6 +936,10 @@ static inline int __init activate_vmi(vo para_fill(safe_halt, Halt); +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + /* * Alternative instruction rewriting doesn't happen soon enough * to convert VMI_IRET to a call instead of a jump; so we have diff -NurpP --minimal linux-2.6.22.19/arch/i386/kernel/vmlinux.lds.S linux-2.6.22.19-g-v/arch/i386/kernel/vmlinux.lds.S --- linux-2.6.22.19/arch/i386/kernel/vmlinux.lds.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/kernel/vmlinux.lds.S 2008-03-04 08:55:59.000000000 +0100 @@ -21,6 +21,13 @@ #include #include #include +#include + +#ifdef CONFIG_X86_PAE +#define PMD_SHIFT 21 +#else +#define PMD_SHIFT 22 +#endif OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) @@ -28,22 +35,124 @@ ENTRY(phys_startup_32) jiffies = jiffies_64; PHDRS { - text PT_LOAD FLAGS(5); /* R_E */ - data PT_LOAD FLAGS(7); /* RWE */ - note PT_NOTE FLAGS(0); /* ___ */ + initdata PT_LOAD FLAGS(6); /* RW_ */ + percpu PT_LOAD FLAGS(6); /* RW_ */ + inittext PT_LOAD FLAGS(5); /* R_E */ + text PT_LOAD FLAGS(5); /* R_E */ + rodata PT_LOAD FLAGS(4); /* R__ */ + data PT_LOAD FLAGS(6); /* RW_ */ + note PT_NOTE FLAGS(0); /* ___ */ } SECTIONS { . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR; - phys_startup_32 = startup_32 - LOAD_OFFSET; + phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET; - .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) { - _text = .; /* Text and read-only data */ + .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) { + BYTE(0xEA) /* jmp far */ + LONG(phys_startup_32) + SHORT(__BOOT_CS) + } :initdata + + /* might get freed after init */ + . = ALIGN(4096); + .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { + __smp_locks = .; + *(.smp_locks) + __smp_locks_end = .; + } + /* will be freed after init + * Following ALIGN() is required to make sure no other data falls on the + * same page where __smp_alt_end is pointing as that page might be freed + * after boot. Always make sure that ALIGN() directive is present after + * the section which contains __smp_alt_end. + */ + . = ALIGN(4096); + + /* will be freed after init */ + .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { + __init_begin = .; + *(.init.data) + } + . = ALIGN(16); + .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { + __initcall_start = .; + INITCALLS + __initcall_end = .; + } + .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + SECURITY_INIT + . = ALIGN(4); + .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { + __alt_instructions = .; + *(.altinstructions) + __alt_instructions_end = .; + } + .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { + *(.altinstr_replacement) + } + . = ALIGN(4); + .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { + __parainstructions = .; + *(.parainstructions) + __parainstructions_end = .; + } + .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } +#if defined(CONFIG_BLK_DEV_INITRD) + . = ALIGN(4096); + .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } +#endif + . = ALIGN(4096); + per_cpu_start = .; + .data.percpu (0) : AT(ADDR(.data.percpu) - LOAD_OFFSET + per_cpu_start) { + __per_cpu_start = . + per_cpu_start; + LONG(0) + *(.data.percpu) + __per_cpu_end = . + per_cpu_start; + } :percpu + . += per_cpu_start; + + /* read-only */ + + . = ALIGN(4096); /* Init code and data */ + .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { + _sinittext = .; + *(.init.text) + _einittext = .; + } :inittext + + /* .exit.text is discard at runtime, not link time, to deal with references + from .altinstructions and .eh_frame */ + .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { *(.exit.text) } + + .filler : AT(ADDR(.filler) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { + BYTE(0) + . = ALIGN(4*1024*1024) - 1; + } + + /* freed after init ends here */ + + .text.head : AT(ADDR(.text.head) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { + __init_end = . + __KERNEL_TEXT_OFFSET; + _text = .; /* Text and read-only data */ *(.text.head) } :text = 0x9090 /* read-only */ - .text : AT(ADDR(.text) - LOAD_OFFSET) { + .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { TEXT_TEXT SCHED_TEXT LOCK_TEXT @@ -53,12 +162,13 @@ SECTIONS _etext = .; /* End of text section */ } :text = 0x9090 + . += __KERNEL_TEXT_OFFSET; . = ALIGN(16); /* Exception table */ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; *(__ex_table) __stop___ex_table = .; - } + } :rodata BUG_TABLE @@ -71,9 +181,37 @@ SECTIONS RODATA + . = ALIGN(4096); + .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) { + *(.empty_zero_page) + +#ifdef CONFIG_X86_PAE + *(.swapper_pm_dir) +#endif + + *(.swapper_pg_dir) + *(.idt) + } + +#ifdef CONFIG_PAX_KERNEXEC + . = ALIGN(4096); + + .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) { + MODULES_VADDR = .; + BYTE(0) + . += (4 * 1024 * 1024); + . = ALIGN(1 << PMD_SHIFT) - 1; + MODULES_END = .; + } + +#else + . = ALIGN(32); +#endif + /* writeable */ . = ALIGN(4096); .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ + _data = .; DATA_DATA CONSTRUCTORS } :data @@ -86,11 +224,6 @@ SECTIONS __nosave_end = .; } - . = ALIGN(4096); - .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { - *(.data.idt) - } - . = ALIGN(32); .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) @@ -108,85 +241,9 @@ SECTIONS *(.data.init_task) } - /* might get freed after init */ - . = ALIGN(4096); - .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { - __smp_locks = .; - *(.smp_locks) - __smp_locks_end = .; - } - /* will be freed after init - * Following ALIGN() is required to make sure no other data falls on the - * same page where __smp_alt_end is pointing as that page might be freed - * after boot. Always make sure that ALIGN() directive is present after - * the section which contains __smp_alt_end. - */ . = ALIGN(4096); - /* will be freed after init */ - . = ALIGN(4096); /* Init code and data */ - .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { - __init_begin = .; - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } - . = ALIGN(16); - .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } - .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - SECURITY_INIT - . = ALIGN(4); - .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { - __alt_instructions = .; - *(.altinstructions) - __alt_instructions_end = .; - } - .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { - *(.altinstr_replacement) - } - . = ALIGN(4); - .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { - __parainstructions = .; - *(.parainstructions) - __parainstructions_end = .; - } - /* .exit.text is discard at runtime, not link time, to deal with references - from .altinstructions and .eh_frame */ - .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } - .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } -#if defined(CONFIG_BLK_DEV_INITRD) - . = ALIGN(4096); - .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } -#endif - . = ALIGN(4096); - .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { - __per_cpu_start = .; - *(.data.percpu) - __per_cpu_end = .; - } - . = ALIGN(4096); - /* freed after init ends here */ - .bss : AT(ADDR(.bss) - LOAD_OFFSET) { - __init_end = .; __bss_start = .; /* BSS */ *(.bss.page_aligned) *(.bss) diff -NurpP --minimal linux-2.6.22.19/arch/i386/lib/checksum.S linux-2.6.22.19-g-v/arch/i386/lib/checksum.S --- linux-2.6.22.19/arch/i386/lib/checksum.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/lib/checksum.S 2008-03-04 08:55:59.000000000 +0100 @@ -28,7 +28,8 @@ #include #include #include - +#include + /* * computes a partial checksum, e.g. for TCP/UDP fragments */ @@ -304,9 +305,22 @@ unsigned int csum_partial_copy_generic ( #define ARGBASE 16 #define FP 12 - -ENTRY(csum_partial_copy_generic) + +ENTRY(csum_partial_copy_generic_to_user) CFI_STARTPROC + pushl $(__USER_DS) + CFI_ADJUST_CFA_OFFSET 4 + popl %es + CFI_ADJUST_CFA_OFFSET -4 + jmp csum_partial_copy_generic + +ENTRY(csum_partial_copy_generic_from_user) + pushl $(__USER_DS) + CFI_ADJUST_CFA_OFFSET 4 + popl %ds + CFI_ADJUST_CFA_OFFSET -4 + +ENTRY(csum_partial_copy_generic) subl $4,%esp CFI_ADJUST_CFA_OFFSET 4 pushl %edi @@ -331,7 +345,7 @@ ENTRY(csum_partial_copy_generic) jmp 4f SRC(1: movw (%esi), %bx ) addl $2, %esi -DST( movw %bx, (%edi) ) +DST( movw %bx, %es:(%edi) ) addl $2, %edi addw %bx, %ax adcl $0, %eax @@ -343,30 +357,30 @@ DST( movw %bx, (%edi) ) SRC(1: movl (%esi), %ebx ) SRC( movl 4(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, (%edi) ) +DST( movl %ebx, %es:(%edi) ) adcl %edx, %eax -DST( movl %edx, 4(%edi) ) +DST( movl %edx, %es:4(%edi) ) SRC( movl 8(%esi), %ebx ) SRC( movl 12(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 8(%edi) ) +DST( movl %ebx, %es:8(%edi) ) adcl %edx, %eax -DST( movl %edx, 12(%edi) ) +DST( movl %edx, %es:12(%edi) ) SRC( movl 16(%esi), %ebx ) SRC( movl 20(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 16(%edi) ) +DST( movl %ebx, %es:16(%edi) ) adcl %edx, %eax -DST( movl %edx, 20(%edi) ) +DST( movl %edx, %es:20(%edi) ) SRC( movl 24(%esi), %ebx ) SRC( movl 28(%esi), %edx ) adcl %ebx, %eax -DST( movl %ebx, 24(%edi) ) +DST( movl %ebx, %es:24(%edi) ) adcl %edx, %eax -DST( movl %edx, 28(%edi) ) +DST( movl %edx, %es:28(%edi) ) lea 32(%esi), %esi lea 32(%edi), %edi @@ -380,7 +394,7 @@ DST( movl %edx, 28(%edi) ) shrl $2, %edx # This clears CF SRC(3: movl (%esi), %ebx ) adcl %ebx, %eax -DST( movl %ebx, (%edi) ) +DST( movl %ebx, %es:(%edi) ) lea 4(%esi), %esi lea 4(%edi), %edi dec %edx @@ -392,12 +406,12 @@ DST( movl %ebx, (%edi) ) jb 5f SRC( movw (%esi), %cx ) leal 2(%esi), %esi -DST( movw %cx, (%edi) ) +DST( movw %cx, %es:(%edi) ) leal 2(%edi), %edi je 6f shll $16,%ecx SRC(5: movb (%esi), %cl ) -DST( movb %cl, (%edi) ) +DST( movb %cl, %es:(%edi) ) 6: addl %ecx, %eax adcl $0, %eax 7: @@ -408,7 +422,7 @@ DST( movb %cl, (%edi) ) 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) # zero the complete destination - computing the rest # is too much work @@ -421,11 +435,19 @@ DST( movb %cl, (%edi) ) 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT,(%ebx) + movl $-EFAULT,%ss:(%ebx) jmp 5000b .previous + pushl %ss + CFI_ADJUST_CFA_OFFSET 4 + popl %ds + CFI_ADJUST_CFA_OFFSET -4 + pushl %ss + CFI_ADJUST_CFA_OFFSET 4 + popl %es + CFI_ADJUST_CFA_OFFSET -4 popl %ebx CFI_ADJUST_CFA_OFFSET -4 CFI_RESTORE ebx @@ -439,26 +461,41 @@ DST( movb %cl, (%edi) ) CFI_ADJUST_CFA_OFFSET -4 ret CFI_ENDPROC -ENDPROC(csum_partial_copy_generic) +ENDPROC(csum_partial_copy_generic_to_user) #else /* Version for PentiumII/PPro */ #define ROUND1(x) \ + nop; nop; nop; \ SRC(movl x(%esi), %ebx ) ; \ addl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; + DST(movl %ebx, %es:x(%edi)) ; #define ROUND(x) \ + nop; nop; nop; \ SRC(movl x(%esi), %ebx ) ; \ adcl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; + DST(movl %ebx, %es:x(%edi)) ; #define ARGBASE 12 - -ENTRY(csum_partial_copy_generic) + +ENTRY(csum_partial_copy_generic_to_user) CFI_STARTPROC + pushl $(__USER_DS) + CFI_ADJUST_CFA_OFFSET 4 + popl %es + CFI_ADJUST_CFA_OFFSET -4 + jmp csum_partial_copy_generic + +ENTRY(csum_partial_copy_generic_from_user) + pushl $(__USER_DS) + CFI_ADJUST_CFA_OFFSET 4 + popl %ds + CFI_ADJUST_CFA_OFFSET -4 + +ENTRY(csum_partial_copy_generic) pushl %ebx CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET ebx, 0 @@ -482,7 +519,7 @@ ENTRY(csum_partial_copy_generic) subl %ebx, %edi lea -1(%esi),%edx andl $-32,%edx - lea 3f(%ebx,%ebx), %ebx + lea 3f(%ebx,%ebx,2), %ebx testl %esi, %esi jmp *%ebx 1: addl $64,%esi @@ -503,19 +540,19 @@ ENTRY(csum_partial_copy_generic) jb 5f SRC( movw (%esi), %dx ) leal 2(%esi), %esi -DST( movw %dx, (%edi) ) +DST( movw %dx, %es:(%edi) ) leal 2(%edi), %edi je 6f shll $16,%edx 5: SRC( movb (%esi), %dl ) -DST( movb %dl, (%edi) ) +DST( movb %dl, %es:(%edi) ) 6: addl %edx, %eax adcl $0, %eax 7: .section .fixup, "ax" 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) # zero the complete destination (computing the rest is too much work) movl ARGBASE+8(%esp),%edi # dst movl ARGBASE+12(%esp),%ecx # len @@ -523,10 +560,18 @@ DST( movb %dl, (%edi) ) rep; stosb jmp 7b 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT, (%ebx) + movl $-EFAULT, %ss:(%ebx) jmp 7b .previous + pushl %ss + CFI_ADJUST_CFA_OFFSET 4 + popl %ds + CFI_ADJUST_CFA_OFFSET -4 + pushl %ss + CFI_ADJUST_CFA_OFFSET 4 + popl %es + CFI_ADJUST_CFA_OFFSET -4 popl %esi CFI_ADJUST_CFA_OFFSET -4 CFI_RESTORE esi @@ -538,7 +583,7 @@ DST( movb %dl, (%edi) ) CFI_RESTORE ebx ret CFI_ENDPROC -ENDPROC(csum_partial_copy_generic) +ENDPROC(csum_partial_copy_generic_to_user) #undef ROUND #undef ROUND1 diff -NurpP --minimal linux-2.6.22.19/arch/i386/lib/getuser.S linux-2.6.22.19-g-v/arch/i386/lib/getuser.S --- linux-2.6.22.19/arch/i386/lib/getuser.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/lib/getuser.S 2008-03-04 08:55:59.000000000 +0100 @@ -11,7 +11,7 @@ #include #include #include - +#include /* * __get_user_X @@ -31,7 +31,11 @@ ENTRY(__get_user_1) GET_THREAD_INFO(%edx) cmpl TI_addr_limit(%edx),%eax jae bad_get_user + pushl $(__USER_DS) + popl %ds 1: movzbl (%eax),%edx + pushl %ss + pop %ds xorl %eax,%eax ret CFI_ENDPROC @@ -44,7 +48,11 @@ ENTRY(__get_user_2) GET_THREAD_INFO(%edx) cmpl TI_addr_limit(%edx),%eax jae bad_get_user + pushl $(__USER_DS) + popl %ds 2: movzwl -1(%eax),%edx + pushl %ss + pop %ds xorl %eax,%eax ret CFI_ENDPROC @@ -57,7 +65,11 @@ ENTRY(__get_user_4) GET_THREAD_INFO(%edx) cmpl TI_addr_limit(%edx),%eax jae bad_get_user + pushl $(__USER_DS) + popl %ds 3: movl -3(%eax),%edx + pushl %ss + pop %ds xorl %eax,%eax ret CFI_ENDPROC @@ -65,6 +77,8 @@ ENDPROC(__get_user_4) bad_get_user: CFI_STARTPROC + pushl %ss + pop %ds xorl %edx,%edx movl $-14,%eax ret diff -NurpP --minimal linux-2.6.22.19/arch/i386/lib/mmx.c linux-2.6.22.19-g-v/arch/i386/lib/mmx.c --- linux-2.6.22.19/arch/i386/lib/mmx.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/lib/mmx.c 2008-03-04 08:55:59.000000000 +0100 @@ -30,6 +30,7 @@ void *_mmx_memcpy(void *to, const void * { void *p; int i; + unsigned long cr0; if (unlikely(in_interrupt())) return __memcpy(to, from, len); @@ -40,52 +41,80 @@ void *_mmx_memcpy(void *to, const void * kernel_fpu_begin(); __asm__ __volatile__ ( - "1: prefetch (%0)\n" /* This set is 28 bytes */ - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" /* This set is 28 bytes */ + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from) ); + : "=&r" (cr0) : "r" (from) : "ax"); for(; i>5; i--) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movq 8(%0), %%mm1\n" - " movq 16(%0), %%mm2\n" - " movq 24(%0), %%mm3\n" - " movq %%mm0, (%1)\n" - " movq %%mm1, 8(%1)\n" - " movq %%mm2, 16(%1)\n" - " movq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm0\n" - " movq 40(%0), %%mm1\n" - " movq 48(%0), %%mm2\n" - " movq 56(%0), %%mm3\n" - " movq %%mm0, 32(%1)\n" - " movq %%mm1, 40(%1)\n" - " movq %%mm2, 48(%1)\n" - " movq %%mm3, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movq 8(%1), %%mm1\n" + " movq 16(%1), %%mm2\n" + " movq 24(%1), %%mm3\n" + " movq %%mm0, (%2)\n" + " movq %%mm1, 8(%2)\n" + " movq %%mm2, 16(%2)\n" + " movq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm0\n" + " movq 40(%1), %%mm1\n" + " movq 48(%1), %%mm2\n" + " movq 56(%1), %%mm3\n" + " movq %%mm0, 32(%2)\n" + " movq %%mm1, 40(%2)\n" + " movq %%mm2, 48(%2)\n" + " movq %%mm3, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from), "r" (to) : "memory"); + : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from+=64; to+=64; } @@ -164,6 +193,7 @@ static void fast_clear_page(void *page) static void fast_copy_page(void *to, void *from) { int i; + unsigned long cr0; kernel_fpu_begin(); @@ -171,51 +201,79 @@ static void fast_copy_page(void *to, voi * but that is for later. -AV */ __asm__ __volatile__ ( - "1: prefetch (%0)\n" - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from) ); + : "=&r" (cr0) : "r" (from) : "ax"); for(i=0; i<(4096-320)/64; i++) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movntq %%mm0, (%1)\n" - " movq 8(%0), %%mm1\n" - " movntq %%mm1, 8(%1)\n" - " movq 16(%0), %%mm2\n" - " movntq %%mm2, 16(%1)\n" - " movq 24(%0), %%mm3\n" - " movntq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm4\n" - " movntq %%mm4, 32(%1)\n" - " movq 40(%0), %%mm5\n" - " movntq %%mm5, 40(%1)\n" - " movq 48(%0), %%mm6\n" - " movntq %%mm6, 48(%1)\n" - " movq 56(%0), %%mm7\n" - " movntq %%mm7, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movntq %%mm0, (%2)\n" + " movq 8(%1), %%mm1\n" + " movntq %%mm1, 8(%2)\n" + " movq 16(%1), %%mm2\n" + " movntq %%mm2, 16(%2)\n" + " movq 24(%1), %%mm3\n" + " movntq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm4\n" + " movntq %%mm4, 32(%2)\n" + " movq 40(%1), %%mm5\n" + " movntq %%mm5, 40(%2)\n" + " movq 48(%1), %%mm6\n" + " movntq %%mm6, 48(%2)\n" + " movq 56(%1), %%mm7\n" + " movntq %%mm7, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from), "r" (to) : "memory"); + : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from+=64; to+=64; } @@ -296,56 +354,84 @@ static void fast_clear_page(void *page) static void fast_copy_page(void *to, void *from) { int i; - - + unsigned long cr0; + kernel_fpu_begin(); __asm__ __volatile__ ( - "1: prefetch (%0)\n" - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" + "1: prefetch (%1)\n" + " prefetch 64(%1)\n" + " prefetch 128(%1)\n" + " prefetch 192(%1)\n" + " prefetch 256(%1)\n" "2: \n" ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + "3: \n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from) ); + : "=&r" (cr0) : "r" (from) : "ax"); for(i=0; i<4096/64; i++) { __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movq 8(%0), %%mm1\n" - " movq 16(%0), %%mm2\n" - " movq 24(%0), %%mm3\n" - " movq %%mm0, (%1)\n" - " movq %%mm1, 8(%1)\n" - " movq %%mm2, 16(%1)\n" - " movq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm0\n" - " movq 40(%0), %%mm1\n" - " movq 48(%0), %%mm2\n" - " movq 56(%0), %%mm3\n" - " movq %%mm0, 32(%1)\n" - " movq %%mm1, 40(%1)\n" - " movq %%mm2, 48(%1)\n" - " movq %%mm3, 56(%1)\n" + "1: prefetch 320(%1)\n" + "2: movq (%1), %%mm0\n" + " movq 8(%1), %%mm1\n" + " movq 16(%1), %%mm2\n" + " movq 24(%1), %%mm3\n" + " movq %%mm0, (%2)\n" + " movq %%mm1, 8(%2)\n" + " movq %%mm2, 16(%2)\n" + " movq %%mm3, 24(%2)\n" + " movq 32(%1), %%mm0\n" + " movq 40(%1), %%mm1\n" + " movq 48(%1), %%mm2\n" + " movq 56(%1), %%mm3\n" + " movq %%mm0, 32(%2)\n" + " movq %%mm1, 40(%2)\n" + " movq %%mm2, 48(%2)\n" + " movq %%mm3, 56(%2)\n" ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + "3:\n" + +#ifdef CONFIG_PAX_KERNEXEC + " movl %%cr0, %0\n" + " movl %0, %%eax\n" + " andl $0xFFFEFFFF, %%eax\n" + " movl %%eax, %%cr0\n" +#endif + + " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ + +#ifdef CONFIG_PAX_KERNEXEC + " movl %0, %%cr0\n" +#endif + " jmp 2b\n" ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 1b, 3b\n" ".previous" - : : "r" (from), "r" (to) : "memory"); + : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); from+=64; to+=64; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/lib/putuser.S linux-2.6.22.19-g-v/arch/i386/lib/putuser.S --- linux-2.6.22.19/arch/i386/lib/putuser.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/lib/putuser.S 2008-03-04 08:55:59.000000000 +0100 @@ -11,7 +11,7 @@ #include #include #include - +#include /* * __put_user_X @@ -41,7 +41,11 @@ ENTRY(__put_user_1) ENTER cmpl TI_addr_limit(%ebx),%ecx jae bad_put_user + pushl $(__USER_DS) + popl %ds 1: movb %al,(%ecx) + pushl %ss + popl %ds xorl %eax,%eax EXIT ENDPROC(__put_user_1) @@ -52,7 +56,11 @@ ENTRY(__put_user_2) subl $1,%ebx cmpl %ebx,%ecx jae bad_put_user + pushl $(__USER_DS) + popl %ds 2: movw %ax,(%ecx) + pushl %ss + popl %ds xorl %eax,%eax EXIT ENDPROC(__put_user_2) @@ -63,7 +71,11 @@ ENTRY(__put_user_4) subl $3,%ebx cmpl %ebx,%ecx jae bad_put_user + pushl $(__USER_DS) + popl %ds 3: movl %eax,(%ecx) + pushl %ss + popl %ds xorl %eax,%eax EXIT ENDPROC(__put_user_4) @@ -74,8 +86,12 @@ ENTRY(__put_user_8) subl $7,%ebx cmpl %ebx,%ecx jae bad_put_user + pushl $(__USER_DS) + popl %ds 4: movl %eax,(%ecx) 5: movl %edx,4(%ecx) + pushl %ss + popl %ds xorl %eax,%eax EXIT ENDPROC(__put_user_8) @@ -85,6 +101,10 @@ bad_put_user: CFI_DEF_CFA esp, 2*4 CFI_OFFSET eip, -1*4 CFI_OFFSET ebx, -2*4 + pushl %ss + CFI_ADJUST_CFA_OFFSET 4 + popl %ds + CFI_ADJUST_CFA_OFFSET -4 movl $-14,%eax EXIT END(bad_put_user) diff -NurpP --minimal linux-2.6.22.19/arch/i386/lib/usercopy.c linux-2.6.22.19-g-v/arch/i386/lib/usercopy.c --- linux-2.6.22.19/arch/i386/lib/usercopy.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/lib/usercopy.c 2008-03-04 08:55:59.000000000 +0100 @@ -29,34 +29,41 @@ static inline int __movsl_is_ok(unsigned * Copy a null terminated string from userspace. */ -#define __do_strncpy_from_user(dst,src,count,res) \ -do { \ - int __d0, __d1, __d2; \ - might_sleep(); \ - __asm__ __volatile__( \ - " testl %1,%1\n" \ - " jz 2f\n" \ - "0: lodsb\n" \ - " stosb\n" \ - " testb %%al,%%al\n" \ - " jz 1f\n" \ - " decl %1\n" \ - " jnz 0b\n" \ - "1: subl %1,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: movl %5,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 0b,3b\n" \ - ".previous" \ - : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \ - "=&D" (__d2) \ - : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ - : "memory"); \ -} while (0) +static long __do_strncpy_from_user(char *dst, const char __user *src, long count) +{ + int __d0, __d1, __d2; + long res = -EFAULT; + + might_sleep(); + __asm__ __volatile__( + " movw %w10,%%ds\n" + " testl %1,%1\n" + " jz 2f\n" + "0: lodsb\n" + " stosb\n" + " testb %%al,%%al\n" + " jz 1f\n" + " decl %1\n" + " jnz 0b\n" + "1: subl %1,%0\n" + "2:\n" + " pushl %%ss\n" + " popl %%ds\n" + ".section .fixup,\"ax\"\n" + "3: movl %5,%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,3b\n" + ".previous" + : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), + "=&D" (__d2) + : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst), + "r"(__USER_DS) + : "memory"); + return res; +} /** * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. @@ -81,9 +88,7 @@ do { \ long __strncpy_from_user(char *dst, const char __user *src, long count) { - long res; - __do_strncpy_from_user(dst, src, count, res); - return res; + return __do_strncpy_from_user(dst, src, count); } EXPORT_SYMBOL(__strncpy_from_user); @@ -110,7 +115,7 @@ strncpy_from_user(char *dst, const char { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) - __do_strncpy_from_user(dst, src, count, res); + res = __do_strncpy_from_user(dst, src, count); return res; } EXPORT_SYMBOL(strncpy_from_user); @@ -119,27 +124,33 @@ EXPORT_SYMBOL(strncpy_from_user); * Zero Userspace */ -#define __do_clear_user(addr,size) \ -do { \ - int __d0; \ - might_sleep(); \ - __asm__ __volatile__( \ - "0: rep; stosl\n" \ - " movl %2,%0\n" \ - "1: rep; stosb\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: lea 0(%2,%0,4),%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 0b,3b\n" \ - " .long 1b,2b\n" \ - ".previous" \ - : "=&c"(size), "=&D" (__d0) \ - : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \ -} while (0) +static unsigned long __do_clear_user(void __user *addr, unsigned long size) +{ + int __d0; + + might_sleep(); + __asm__ __volatile__( + " movw %w6,%%es\n" + "0: rep; stosl\n" + " movl %2,%0\n" + "1: rep; stosb\n" + "2:\n" + " pushl %%ss\n" + " popl %%es\n" + ".section .fixup,\"ax\"\n" + "3: lea 0(%2,%0,4),%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,3b\n" + " .long 1b,2b\n" + ".previous" + : "=&c"(size), "=&D" (__d0) + : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0), + "r"(__USER_DS)); + return size; +} /** * clear_user: - Zero a block of memory in user space. @@ -156,7 +167,7 @@ clear_user(void __user *to, unsigned lon { might_sleep(); if (access_ok(VERIFY_WRITE, to, n)) - __do_clear_user(to, n); + n = __do_clear_user(to, n); return n; } EXPORT_SYMBOL(clear_user); @@ -175,8 +186,7 @@ EXPORT_SYMBOL(clear_user); unsigned long __clear_user(void __user *to, unsigned long n) { - __do_clear_user(to, n); - return n; + return __do_clear_user(to, n); } EXPORT_SYMBOL(__clear_user); @@ -199,14 +209,17 @@ long strnlen_user(const char __user *s, might_sleep(); __asm__ __volatile__( + " movw %w8,%%es\n" " testl %0, %0\n" " jz 3f\n" - " andl %0,%%ecx\n" + " movl %0,%%ecx\n" "0: repne; scasb\n" " setne %%al\n" " subl %%ecx,%0\n" " addl %0,%%eax\n" "1:\n" + " pushl %%ss\n" + " popl %%es\n" ".section .fixup,\"ax\"\n" "2: xorl %%eax,%%eax\n" " jmp 1b\n" @@ -218,7 +231,7 @@ long strnlen_user(const char __user *s, " .long 0b,2b\n" ".previous" :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp) - :"0" (n), "1" (s), "2" (0), "3" (mask) + :"0" (n), "1" (s), "2" (0), "3" (mask), "r" (__USER_DS) :"cc"); return res & mask; } @@ -226,10 +239,11 @@ EXPORT_SYMBOL(strnlen_user); #ifdef CONFIG_X86_INTEL_USERCOPY static unsigned long -__copy_user_intel(void __user *to, const void *from, unsigned long size) +__generic_copy_to_user_intel(void __user *to, const void *from, unsigned long size) { int d0, d1; __asm__ __volatile__( + " movw %w6, %%es\n" " .align 2,0x90\n" "1: movl 32(%4), %%eax\n" " cmpl $67, %0\n" @@ -238,36 +252,36 @@ __copy_user_intel(void __user *to, const " .align 2,0x90\n" "3: movl 0(%4), %%eax\n" "4: movl 4(%4), %%edx\n" - "5: movl %%eax, 0(%3)\n" - "6: movl %%edx, 4(%3)\n" + "5: movl %%eax, %%es:0(%3)\n" + "6: movl %%edx, %%es:4(%3)\n" "7: movl 8(%4), %%eax\n" "8: movl 12(%4),%%edx\n" - "9: movl %%eax, 8(%3)\n" - "10: movl %%edx, 12(%3)\n" + "9: movl %%eax, %%es:8(%3)\n" + "10: movl %%edx, %%es:12(%3)\n" "11: movl 16(%4), %%eax\n" "12: movl 20(%4), %%edx\n" - "13: movl %%eax, 16(%3)\n" - "14: movl %%edx, 20(%3)\n" + "13: movl %%eax, %%es:16(%3)\n" + "14: movl %%edx, %%es:20(%3)\n" "15: movl 24(%4), %%eax\n" "16: movl 28(%4), %%edx\n" - "17: movl %%eax, 24(%3)\n" - "18: movl %%edx, 28(%3)\n" + "17: movl %%eax, %%es:24(%3)\n" + "18: movl %%edx, %%es:28(%3)\n" "19: movl 32(%4), %%eax\n" "20: movl 36(%4), %%edx\n" - "21: movl %%eax, 32(%3)\n" - "22: movl %%edx, 36(%3)\n" + "21: movl %%eax, %%es:32(%3)\n" + "22: movl %%edx, %%es:36(%3)\n" "23: movl 40(%4), %%eax\n" "24: movl 44(%4), %%edx\n" - "25: movl %%eax, 40(%3)\n" - "26: movl %%edx, 44(%3)\n" + "25: movl %%eax, %%es:40(%3)\n" + "26: movl %%edx, %%es:44(%3)\n" "27: movl 48(%4), %%eax\n" "28: movl 52(%4), %%edx\n" - "29: movl %%eax, 48(%3)\n" - "30: movl %%edx, 52(%3)\n" + "29: movl %%eax, %%es:48(%3)\n" + "30: movl %%edx, %%es:52(%3)\n" "31: movl 56(%4), %%eax\n" "32: movl 60(%4), %%edx\n" - "33: movl %%eax, 56(%3)\n" - "34: movl %%edx, 60(%3)\n" + "33: movl %%eax, %%es:56(%3)\n" + "34: movl %%edx, %%es:60(%3)\n" " addl $-64, %0\n" " addl $64, %4\n" " addl $64, %3\n" @@ -281,6 +295,8 @@ __copy_user_intel(void __user *to, const "36: movl %%eax, %0\n" "37: rep; movsb\n" "100:\n" + " pushl %%ss\n" + " popl %%es\n" ".section .fixup,\"ax\"\n" "101: lea 0(%%eax,%0,4),%0\n" " jmp 100b\n" @@ -327,7 +343,117 @@ __copy_user_intel(void __user *to, const " .long 99b,101b\n" ".previous" : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) + : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) + : "eax", "edx", "memory"); + return size; +} + +static unsigned long +__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size) +{ + int d0, d1; + __asm__ __volatile__( + " movw %w6, %%ds\n" + " .align 2,0x90\n" + "1: movl 32(%4), %%eax\n" + " cmpl $67, %0\n" + " jbe 3f\n" + "2: movl 64(%4), %%eax\n" + " .align 2,0x90\n" + "3: movl 0(%4), %%eax\n" + "4: movl 4(%4), %%edx\n" + "5: movl %%eax, %%es:0(%3)\n" + "6: movl %%edx, %%es:4(%3)\n" + "7: movl 8(%4), %%eax\n" + "8: movl 12(%4),%%edx\n" + "9: movl %%eax, %%es:8(%3)\n" + "10: movl %%edx, %%es:12(%3)\n" + "11: movl 16(%4), %%eax\n" + "12: movl 20(%4), %%edx\n" + "13: movl %%eax, %%es:16(%3)\n" + "14: movl %%edx, %%es:20(%3)\n" + "15: movl 24(%4), %%eax\n" + "16: movl 28(%4), %%edx\n" + "17: movl %%eax, %%es:24(%3)\n" + "18: movl %%edx, %%es:28(%3)\n" + "19: movl 32(%4), %%eax\n" + "20: movl 36(%4), %%edx\n" + "21: movl %%eax, %%es:32(%3)\n" + "22: movl %%edx, %%es:36(%3)\n" + "23: movl 40(%4), %%eax\n" + "24: movl 44(%4), %%edx\n" + "25: movl %%eax, %%es:40(%3)\n" + "26: movl %%edx, %%es:44(%3)\n" + "27: movl 48(%4), %%eax\n" + "28: movl 52(%4), %%edx\n" + "29: movl %%eax, %%es:48(%3)\n" + "30: movl %%edx, %%es:52(%3)\n" + "31: movl 56(%4), %%eax\n" + "32: movl 60(%4), %%edx\n" + "33: movl %%eax, %%es:56(%3)\n" + "34: movl %%edx, %%es:60(%3)\n" + " addl $-64, %0\n" + " addl $64, %4\n" + " addl $64, %3\n" + " cmpl $63, %0\n" + " ja 1b\n" + "35: movl %0, %%eax\n" + " shrl $2, %0\n" + " andl $3, %%eax\n" + " cld\n" + "99: rep; movsl\n" + "36: movl %%eax, %0\n" + "37: rep; movsb\n" + "100:\n" + " pushl %%ss\n" + " popl %%ds\n" + ".section .fixup,\"ax\"\n" + "101: lea 0(%%eax,%0,4),%0\n" + " jmp 100b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,100b\n" + " .long 2b,100b\n" + " .long 3b,100b\n" + " .long 4b,100b\n" + " .long 5b,100b\n" + " .long 6b,100b\n" + " .long 7b,100b\n" + " .long 8b,100b\n" + " .long 9b,100b\n" + " .long 10b,100b\n" + " .long 11b,100b\n" + " .long 12b,100b\n" + " .long 13b,100b\n" + " .long 14b,100b\n" + " .long 15b,100b\n" + " .long 16b,100b\n" + " .long 17b,100b\n" + " .long 18b,100b\n" + " .long 19b,100b\n" + " .long 20b,100b\n" + " .long 21b,100b\n" + " .long 22b,100b\n" + " .long 23b,100b\n" + " .long 24b,100b\n" + " .long 25b,100b\n" + " .long 26b,100b\n" + " .long 27b,100b\n" + " .long 28b,100b\n" + " .long 29b,100b\n" + " .long 30b,100b\n" + " .long 31b,100b\n" + " .long 32b,100b\n" + " .long 33b,100b\n" + " .long 34b,100b\n" + " .long 35b,100b\n" + " .long 36b,100b\n" + " .long 37b,100b\n" + " .long 99b,101b\n" + ".previous" + : "=&c"(size), "=&D" (d0), "=&S" (d1) + : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) : "eax", "edx", "memory"); return size; } @@ -337,6 +463,7 @@ __copy_user_zeroing_intel(void *to, cons { int d0, d1; __asm__ __volatile__( + " movw %w6, %%ds\n" " .align 2,0x90\n" "0: movl 32(%4), %%eax\n" " cmpl $67, %0\n" @@ -345,36 +472,36 @@ __copy_user_zeroing_intel(void *to, cons " .align 2,0x90\n" "2: movl 0(%4), %%eax\n" "21: movl 4(%4), %%edx\n" - " movl %%eax, 0(%3)\n" - " movl %%edx, 4(%3)\n" + " movl %%eax, %%es:0(%3)\n" + " movl %%edx, %%es:4(%3)\n" "3: movl 8(%4), %%eax\n" "31: movl 12(%4),%%edx\n" - " movl %%eax, 8(%3)\n" - " movl %%edx, 12(%3)\n" + " movl %%eax, %%es:8(%3)\n" + " movl %%edx, %%es:12(%3)\n" "4: movl 16(%4), %%eax\n" "41: movl 20(%4), %%edx\n" - " movl %%eax, 16(%3)\n" - " movl %%edx, 20(%3)\n" + " movl %%eax, %%es:16(%3)\n" + " movl %%edx, %%es:20(%3)\n" "10: movl 24(%4), %%eax\n" "51: movl 28(%4), %%edx\n" - " movl %%eax, 24(%3)\n" - " movl %%edx, 28(%3)\n" + " movl %%eax, %%es:24(%3)\n" + " movl %%edx, %%es:28(%3)\n" "11: movl 32(%4), %%eax\n" "61: movl 36(%4), %%edx\n" - " movl %%eax, 32(%3)\n" - " movl %%edx, 36(%3)\n" + " movl %%eax, %%es:32(%3)\n" + " movl %%edx, %%es:36(%3)\n" "12: movl 40(%4), %%eax\n" "71: movl 44(%4), %%edx\n" - " movl %%eax, 40(%3)\n" - " movl %%edx, 44(%3)\n" + " movl %%eax, %%es:40(%3)\n" + " movl %%edx, %%es:44(%3)\n" "13: movl 48(%4), %%eax\n" "81: movl 52(%4), %%edx\n" - " movl %%eax, 48(%3)\n" - " movl %%edx, 52(%3)\n" + " movl %%eax, %%es:48(%3)\n" + " movl %%edx, %%es:52(%3)\n" "14: movl 56(%4), %%eax\n" "91: movl 60(%4), %%edx\n" - " movl %%eax, 56(%3)\n" - " movl %%edx, 60(%3)\n" + " movl %%eax, %%es:56(%3)\n" + " movl %%edx, %%es:60(%3)\n" " addl $-64, %0\n" " addl $64, %4\n" " addl $64, %3\n" @@ -388,6 +515,8 @@ __copy_user_zeroing_intel(void *to, cons " movl %%eax,%0\n" "7: rep; movsb\n" "8:\n" + " pushl %%ss\n" + " popl %%ds\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" "16: pushl %0\n" @@ -422,7 +551,7 @@ __copy_user_zeroing_intel(void *to, cons " .long 7b,16b\n" ".previous" : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) + : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) : "eax", "edx", "memory"); return size; } @@ -438,6 +567,7 @@ static unsigned long __copy_user_zeroing int d0, d1; __asm__ __volatile__( + " movw %w6, %%ds\n" " .align 2,0x90\n" "0: movl 32(%4), %%eax\n" " cmpl $67, %0\n" @@ -446,36 +576,36 @@ static unsigned long __copy_user_zeroing " .align 2,0x90\n" "2: movl 0(%4), %%eax\n" "21: movl 4(%4), %%edx\n" - " movnti %%eax, 0(%3)\n" - " movnti %%edx, 4(%3)\n" + " movnti %%eax, %%es:0(%3)\n" + " movnti %%edx, %%es:4(%3)\n" "3: movl 8(%4), %%eax\n" "31: movl 12(%4),%%edx\n" - " movnti %%eax, 8(%3)\n" - " movnti %%edx, 12(%3)\n" + " movnti %%eax, %%es:8(%3)\n" + " movnti %%edx, %%es:12(%3)\n" "4: movl 16(%4), %%eax\n" "41: movl 20(%4), %%edx\n" - " movnti %%eax, 16(%3)\n" - " movnti %%edx, 20(%3)\n" + " movnti %%eax, %%es:16(%3)\n" + " movnti %%edx, %%es:20(%3)\n" "10: movl 24(%4), %%eax\n" "51: movl 28(%4), %%edx\n" - " movnti %%eax, 24(%3)\n" - " movnti %%edx, 28(%3)\n" + " movnti %%eax, %%es:24(%3)\n" + " movnti %%edx, %%es:28(%3)\n" "11: movl 32(%4), %%eax\n" "61: movl 36(%4), %%edx\n" - " movnti %%eax, 32(%3)\n" - " movnti %%edx, 36(%3)\n" + " movnti %%eax, %%es:32(%3)\n" + " movnti %%edx, %%es:36(%3)\n" "12: movl 40(%4), %%eax\n" "71: movl 44(%4), %%edx\n" - " movnti %%eax, 40(%3)\n" - " movnti %%edx, 44(%3)\n" + " movnti %%eax, %%es:40(%3)\n" + " movnti %%edx, %%es:44(%3)\n" "13: movl 48(%4), %%eax\n" "81: movl 52(%4), %%edx\n" - " movnti %%eax, 48(%3)\n" - " movnti %%edx, 52(%3)\n" + " movnti %%eax, %%es:48(%3)\n" + " movnti %%edx, %%es:52(%3)\n" "14: movl 56(%4), %%eax\n" "91: movl 60(%4), %%edx\n" - " movnti %%eax, 56(%3)\n" - " movnti %%edx, 60(%3)\n" + " movnti %%eax, %%es:56(%3)\n" + " movnti %%edx, %%es:60(%3)\n" " addl $-64, %0\n" " addl $64, %4\n" " addl $64, %3\n" @@ -490,6 +620,8 @@ static unsigned long __copy_user_zeroing " movl %%eax,%0\n" "7: rep; movsb\n" "8:\n" + " pushl %%ss\n" + " popl %%ds\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" "16: pushl %0\n" @@ -524,7 +656,7 @@ static unsigned long __copy_user_zeroing " .long 7b,16b\n" ".previous" : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) + : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) : "eax", "edx", "memory"); return size; } @@ -535,6 +667,7 @@ static unsigned long __copy_user_intel_n int d0, d1; __asm__ __volatile__( + " movw %w6, %%ds\n" " .align 2,0x90\n" "0: movl 32(%4), %%eax\n" " cmpl $67, %0\n" @@ -543,36 +676,36 @@ static unsigned long __copy_user_intel_n " .align 2,0x90\n" "2: movl 0(%4), %%eax\n" "21: movl 4(%4), %%edx\n" - " movnti %%eax, 0(%3)\n" - " movnti %%edx, 4(%3)\n" + " movnti %%eax, %%es:0(%3)\n" + " movnti %%edx, %%es:4(%3)\n" "3: movl 8(%4), %%eax\n" "31: movl 12(%4),%%edx\n" - " movnti %%eax, 8(%3)\n" - " movnti %%edx, 12(%3)\n" + " movnti %%eax, %%es:8(%3)\n" + " movnti %%edx, %%es:12(%3)\n" "4: movl 16(%4), %%eax\n" "41: movl 20(%4), %%edx\n" - " movnti %%eax, 16(%3)\n" - " movnti %%edx, 20(%3)\n" + " movnti %%eax, %%es:16(%3)\n" + " movnti %%edx, %%es:20(%3)\n" "10: movl 24(%4), %%eax\n" "51: movl 28(%4), %%edx\n" - " movnti %%eax, 24(%3)\n" - " movnti %%edx, 28(%3)\n" + " movnti %%eax, %%es:24(%3)\n" + " movnti %%edx, %%es:28(%3)\n" "11: movl 32(%4), %%eax\n" "61: movl 36(%4), %%edx\n" - " movnti %%eax, 32(%3)\n" - " movnti %%edx, 36(%3)\n" + " movnti %%eax, %%es:32(%3)\n" + " movnti %%edx, %%es:36(%3)\n" "12: movl 40(%4), %%eax\n" "71: movl 44(%4), %%edx\n" - " movnti %%eax, 40(%3)\n" - " movnti %%edx, 44(%3)\n" + " movnti %%eax, %%es:40(%3)\n" + " movnti %%edx, %%es:44(%3)\n" "13: movl 48(%4), %%eax\n" "81: movl 52(%4), %%edx\n" - " movnti %%eax, 48(%3)\n" - " movnti %%edx, 52(%3)\n" + " movnti %%eax, %%es:48(%3)\n" + " movnti %%edx, %%es:52(%3)\n" "14: movl 56(%4), %%eax\n" "91: movl 60(%4), %%edx\n" - " movnti %%eax, 56(%3)\n" - " movnti %%edx, 60(%3)\n" + " movnti %%eax, %%es:56(%3)\n" + " movnti %%edx, %%es:60(%3)\n" " addl $-64, %0\n" " addl $64, %4\n" " addl $64, %3\n" @@ -587,6 +720,8 @@ static unsigned long __copy_user_intel_n " movl %%eax,%0\n" "7: rep; movsb\n" "8:\n" + " pushl %%ss\n" + " popl %%ds\n" ".section .fixup,\"ax\"\n" "9: lea 0(%%eax,%0,4),%0\n" "16: jmp 8b\n" @@ -615,7 +750,7 @@ static unsigned long __copy_user_intel_n " .long 7b,16b\n" ".previous" : "=&c"(size), "=&D" (d0), "=&S" (d1) - : "1"(to), "2"(from), "0"(size) + : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) : "eax", "edx", "memory"); return size; } @@ -628,90 +763,146 @@ static unsigned long __copy_user_intel_n */ unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size); -unsigned long __copy_user_intel(void __user *to, const void *from, +unsigned long __generic_copy_to_user_intel(void __user *to, const void *from, + unsigned long size); +unsigned long __generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size); unsigned long __copy_user_zeroing_intel_nocache(void *to, const void __user *from, unsigned long size); #endif /* CONFIG_X86_INTEL_USERCOPY */ /* Generic arbitrary sized copy. */ -#define __copy_user(to,from,size) \ -do { \ - int __d0, __d1, __d2; \ - __asm__ __volatile__( \ - " cmp $7,%0\n" \ - " jbe 1f\n" \ - " movl %1,%0\n" \ - " negl %0\n" \ - " andl $7,%0\n" \ - " subl %0,%3\n" \ - "4: rep; movsb\n" \ - " movl %3,%0\n" \ - " shrl $2,%0\n" \ - " andl $3,%3\n" \ - " .align 2,0x90\n" \ - "0: rep; movsl\n" \ - " movl %3,%0\n" \ - "1: rep; movsb\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "5: addl %3,%0\n" \ - " jmp 2b\n" \ - "3: lea 0(%3,%0,4),%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 4b,5b\n" \ - " .long 0b,3b\n" \ - " .long 1b,2b\n" \ - ".previous" \ - : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ - : "3"(size), "0"(size), "1"(to), "2"(from) \ - : "memory"); \ -} while (0) +static unsigned long +__generic_copy_to_user(void __user *to, const void *from, unsigned long size) +{ + int __d0, __d1, __d2; -#define __copy_user_zeroing(to,from,size) \ -do { \ - int __d0, __d1, __d2; \ - __asm__ __volatile__( \ - " cmp $7,%0\n" \ - " jbe 1f\n" \ - " movl %1,%0\n" \ - " negl %0\n" \ - " andl $7,%0\n" \ - " subl %0,%3\n" \ - "4: rep; movsb\n" \ - " movl %3,%0\n" \ - " shrl $2,%0\n" \ - " andl $3,%3\n" \ - " .align 2,0x90\n" \ - "0: rep; movsl\n" \ - " movl %3,%0\n" \ - "1: rep; movsb\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "5: addl %3,%0\n" \ - " jmp 6f\n" \ - "3: lea 0(%3,%0,4),%0\n" \ - "6: pushl %0\n" \ - " pushl %%eax\n" \ - " xorl %%eax,%%eax\n" \ - " rep; stosb\n" \ - " popl %%eax\n" \ - " popl %0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 4b,5b\n" \ - " .long 0b,3b\n" \ - " .long 1b,6b\n" \ - ".previous" \ - : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ - : "3"(size), "0"(size), "1"(to), "2"(from) \ - : "memory"); \ -} while (0) + __asm__ __volatile__( + " movw %w8,%%es\n" + " cmp $7,%0\n" + " jbe 1f\n" + " movl %1,%0\n" + " negl %0\n" + " andl $7,%0\n" + " subl %0,%3\n" + "4: rep; movsb\n" + " movl %3,%0\n" + " shrl $2,%0\n" + " andl $3,%3\n" + " .align 2,0x90\n" + "0: rep; movsl\n" + " movl %3,%0\n" + "1: rep; movsb\n" + "2:\n" + " pushl %%ss\n" + " popl %%es\n" + ".section .fixup,\"ax\"\n" + "5: addl %3,%0\n" + " jmp 2b\n" + "3: lea 0(%3,%0,4),%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 4b,5b\n" + " .long 0b,3b\n" + " .long 1b,2b\n" + ".previous" + : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) + : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) + : "memory"); + return size; +} + +static unsigned long +__generic_copy_from_user(void *to, const void __user *from, unsigned long size) +{ + int __d0, __d1, __d2; + + __asm__ __volatile__( + " movw %w8,%%ds\n" + " cmp $7,%0\n" + " jbe 1f\n" + " movl %1,%0\n" + " negl %0\n" + " andl $7,%0\n" + " subl %0,%3\n" + "4: rep; movsb\n" + " movl %3,%0\n" + " shrl $2,%0\n" + " andl $3,%3\n" + " .align 2,0x90\n" + "0: rep; movsl\n" + " movl %3,%0\n" + "1: rep; movsb\n" + "2:\n" + " pushl %%ss\n" + " popl %%ds\n" + ".section .fixup,\"ax\"\n" + "5: addl %3,%0\n" + " jmp 2b\n" + "3: lea 0(%3,%0,4),%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 4b,5b\n" + " .long 0b,3b\n" + " .long 1b,2b\n" + ".previous" + : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) + : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) + : "memory"); + return size; +} + +static unsigned long +__copy_user_zeroing(void *to, const void __user *from, unsigned long size) +{ + int __d0, __d1, __d2; + + __asm__ __volatile__( + " movw %w8,%%ds\n" + " cmp $7,%0\n" + " jbe 1f\n" + " movl %1,%0\n" + " negl %0\n" + " andl $7,%0\n" + " subl %0,%3\n" + "4: rep; movsb\n" + " movl %3,%0\n" + " shrl $2,%0\n" + " andl $3,%3\n" + " .align 2,0x90\n" + "0: rep; movsl\n" + " movl %3,%0\n" + "1: rep; movsb\n" + "2:\n" + " pushl %%ss\n" + " popl %%ds\n" + ".section .fixup,\"ax\"\n" + "5: addl %3,%0\n" + " jmp 6f\n" + "3: lea 0(%3,%0,4),%0\n" + "6: pushl %0\n" + " pushl %%eax\n" + " xorl %%eax,%%eax\n" + " rep; stosb\n" + " popl %%eax\n" + " popl %0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 4b,5b\n" + " .long 0b,3b\n" + " .long 1b,6b\n" + ".previous" + : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) + : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) + : "memory"); + return size; +} unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) @@ -774,9 +965,9 @@ survive: } #endif if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + n = __generic_copy_to_user(to, from, n); else - n = __copy_user_intel(to, from, n); + n = __generic_copy_to_user_intel(to, from, n); return n; } EXPORT_SYMBOL(__copy_to_user_ll); @@ -785,7 +976,7 @@ unsigned long __copy_from_user_ll(void * unsigned long n) { if (movsl_is_ok(to, from, n)) - __copy_user_zeroing(to, from, n); + n = __copy_user_zeroing(to, from, n); else n = __copy_user_zeroing_intel(to, from, n); return n; @@ -796,9 +987,9 @@ unsigned long __copy_from_user_ll_nozero unsigned long n) { if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + n = __generic_copy_from_user(to, from, n); else - n = __copy_user_intel((void __user *)to, + n = __generic_copy_from_user_intel((void __user *)to, (const void *)from, n); return n; } @@ -809,11 +1000,11 @@ unsigned long __copy_from_user_ll_nocach { #ifdef CONFIG_X86_INTEL_USERCOPY if ( n > 64 && cpu_has_xmm2) - n = __copy_user_zeroing_intel_nocache(to, from, n); + n = __copy_user_zeroing_intel_nocache(to, from, n); else - __copy_user_zeroing(to, from, n); + n = __copy_user_zeroing(to, from, n); #else - __copy_user_zeroing(to, from, n); + n = __copy_user_zeroing(to, from, n); #endif return n; } @@ -823,11 +1014,11 @@ unsigned long __copy_from_user_ll_nocach { #ifdef CONFIG_X86_INTEL_USERCOPY if ( n > 64 && cpu_has_xmm2) - n = __copy_user_intel_nocache(to, from, n); + n = __copy_user_intel_nocache(to, from, n); else - __copy_user(to, from, n); + n = __generic_copy_from_user(to, from, n); #else - __copy_user(to, from, n); + n = __generic_copy_from_user(to, from, n); #endif return n; } @@ -880,3 +1071,30 @@ copy_from_user(void *to, const void __us return n; } EXPORT_SYMBOL(copy_from_user); + +#ifdef CONFIG_PAX_MEMORY_UDEREF +void __set_fs(mm_segment_t x, int cpu) +{ + unsigned long limit = x.seg; + __u32 a, b; + + current_thread_info()->addr_limit = x; + if (likely(limit)) + limit = (limit - 1UL) >> PAGE_SHIFT; + pack_descriptor(&a, &b, 0UL, limit, 0xF3, 0xC); + write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_DS, a, b); +} + +void set_fs(mm_segment_t x) +{ + __set_fs(x, get_cpu()); + put_cpu_no_resched(); +} +#else +void set_fs(mm_segment_t x) +{ + current_thread_info()->addr_limit = x; +} +#endif + +EXPORT_SYMBOL(set_fs); diff -NurpP --minimal linux-2.6.22.19/arch/i386/mach-default/setup.c linux-2.6.22.19-g-v/arch/i386/mach-default/setup.c --- linux-2.6.22.19/arch/i386/mach-default/setup.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mach-default/setup.c 2008-03-04 08:55:59.000000000 +0100 @@ -35,7 +35,7 @@ void __init pre_intr_init_hook(void) /* * IRQ2 is cascade interrupt to second interrupt controller */ -static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL}; +static struct irqaction irq2 = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL, 0, NULL}; /** * intr_init_hook - post gate setup interrupt initialisation diff -NurpP --minimal linux-2.6.22.19/arch/i386/mach-voyager/voyager_basic.c linux-2.6.22.19-g-v/arch/i386/mach-voyager/voyager_basic.c --- linux-2.6.22.19/arch/i386/mach-voyager/voyager_basic.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mach-voyager/voyager_basic.c 2008-03-04 08:55:59.000000000 +0100 @@ -130,7 +130,7 @@ voyager_memory_detect(int region, __u32 __u8 cmos[4]; ClickMap_t *map; unsigned long map_addr; - unsigned long old; + pte_t old; if(region >= CLICK_ENTRIES) { printk("Voyager: Illegal ClickMap region %d\n", region); @@ -144,7 +144,7 @@ voyager_memory_detect(int region, __u32 /* steal page 0 for this */ old = pg0[0]; - pg0[0] = ((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT); + pg0[0] = __pte((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT); local_flush_tlb(); /* now clear everything out but page 0 */ map = (ClickMap_t *)(map_addr & (~PAGE_MASK)); diff -NurpP --minimal linux-2.6.22.19/arch/i386/mach-voyager/voyager_smp.c linux-2.6.22.19-g-v/arch/i386/mach-voyager/voyager_smp.c --- linux-2.6.22.19/arch/i386/mach-voyager/voyager_smp.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mach-voyager/voyager_smp.c 2008-03-04 08:55:59.000000000 +0100 @@ -554,6 +554,10 @@ do_boot_cpu(__u8 cpu) __u32 *hijack_vector; __u32 start_phys_address = setup_trampoline(); +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + /* There's a clever trick to this: The linux trampoline is * compiled to begin at absolute location zero, so make the * address zero but have the data segment selector compensate @@ -573,7 +577,17 @@ do_boot_cpu(__u8 cpu) init_gdt(cpu); per_cpu(current_task, cpu) = idle; - early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + early_gdt_descr.address = get_cpu_gdt_table(cpu); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -1276,7 +1290,7 @@ smp_local_timer_interrupt(void) per_cpu(prof_counter, cpu); } - update_process_times(user_mode_vm(get_irq_regs())); + update_process_times(user_mode(get_irq_regs())); } if( ((1< */ - -/* - * We need to use the 2-level pagetable functions, but CONFIG_X86_PAE - * keeps that from happenning. If anyone has a better way, I'm listening. - * - * boot_pte_t is defined only if this all works correctly - */ - -#undef CONFIG_X86_PAE #undef CONFIG_PARAVIRT #include #include #include #include #include - -/* - * I'm cheating here. It is known that the two boot PTE pages are - * allocated next to each other. I'm pretending that they're just - * one big array. - */ - -#define BOOT_PTE_PTRS (PTRS_PER_PTE*2) - -static unsigned long boot_pte_index(unsigned long vaddr) -{ - return __pa(vaddr) >> PAGE_SHIFT; -} - -static inline boot_pte_t* boot_vaddr_to_pte(void *address) -{ - boot_pte_t* boot_pg = (boot_pte_t*)pg0; - return &boot_pg[boot_pte_index((unsigned long)address)]; -} +#include /* * This is only for a caller who is clever enough to page-align * phys_addr and virtual_source, and who also has a preference * about which virtual address from which to steal ptes */ -static void __boot_ioremap(unsigned long phys_addr, unsigned long nrpages, - void* virtual_source) +static void __init __boot_ioremap(unsigned long phys_addr, unsigned long nrpages, + char* virtual_source) { - boot_pte_t* pte; - int i; - char *vaddr = virtual_source; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t* pte; + unsigned int i; + unsigned long vaddr = (unsigned long)virtual_source; + + pgd = pgd_offset_k(vaddr); + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); + pte = pte_offset_kernel(pmd, vaddr); - pte = boot_vaddr_to_pte(virtual_source); for (i=0; i < nrpages; i++, phys_addr += PAGE_SIZE, pte++) { set_pte(pte, pfn_pte(phys_addr>>PAGE_SHIFT, PAGE_KERNEL)); - __flush_tlb_one(&vaddr[i*PAGE_SIZE]); + __flush_tlb_one(&virtual_source[i*PAGE_SIZE]); } } diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/extable.c linux-2.6.22.19-g-v/arch/i386/mm/extable.c --- linux-2.6.22.19/arch/i386/mm/extable.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/extable.c 2008-03-04 08:55:59.000000000 +0100 @@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs const struct exception_table_entry *fixup; #ifdef CONFIG_PNPBIOS - if (unlikely(SEGMENT_IS_PNP_CODE(regs->xcs))) + if (unlikely(!(regs->eflags & VM_MASK) && SEGMENT_IS_PNP_CODE(regs->xcs))) { extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; extern u32 pnp_bios_is_utter_crap; diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/fault.c linux-2.6.22.19-g-v/arch/i386/mm/fault.c --- linux-2.6.22.19/arch/i386/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -25,10 +25,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include extern void die(const char *,struct pt_regs *,long); @@ -79,7 +83,8 @@ static inline unsigned long get_segment_ { unsigned long eip = regs->eip; unsigned seg = regs->xcs & 0xffff; - u32 seg_ar, seg_limit, base, *desc; + u32 seg_ar, seg_limit, base; + struct desc_struct *desc; /* Unlikely, but must come before segment checks. */ if (unlikely(regs->eflags & VM_MASK)) { @@ -93,7 +98,7 @@ static inline unsigned long get_segment_ /* By far the most common cases. */ if (likely(SEGMENT_IS_FLAT_CODE(seg))) - return eip; + return eip + (seg == __KERNEL_CS ? __KERNEL_TEXT_OFFSET : 0); /* Check the segment exists, is within the current LDT/GDT size, that kernel/user (ring 0..3) has the appropriate privilege, @@ -111,16 +116,19 @@ static inline unsigned long get_segment_ if (seg & (1<<2)) { /* Must lock the LDT while reading it. */ down(¤t->mm->context.sem); - desc = current->mm->context.ldt; - desc = (void *)desc + (seg & ~7); + if ((seg >> 3) >= current->mm->context.size) { + up(¤t->mm->context.sem); + *eip_limit = 0; + return 1; /* So that returned eip > *eip_limit. */ + } + desc = ¤t->mm->context.ldt[seg >> 3]; } else { /* Must disable preemption while reading the GDT. */ - desc = (u32 *)get_cpu_gdt_table(get_cpu()); - desc = (void *)desc + (seg & ~7); + desc = &get_cpu_gdt_table(get_cpu())[seg >> 3]; } /* Decode the code segment base from the descriptor */ - base = get_desc_base((unsigned long *)desc); + base = get_desc_base(desc); if (seg & (1<<2)) { up(¤t->mm->context.sem); @@ -221,6 +229,30 @@ static noinline void force_sig_info_faul fastcall 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 + +#ifdef CONFIG_PAX_PAGEEXEC +static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + pgd = pgd_offset(mm, address); + if (!pgd_present(*pgd)) + return NULL; + pud = pud_offset(pgd, address); + if (!pud_present(*pud)) + return NULL; + pmd = pmd_offset(pud, address); + if (!pmd_present(*pmd)) + return NULL; + return pmd; +} +#endif + static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) { unsigned index = pgd_index(address); @@ -302,13 +334,20 @@ fastcall void __kprobes do_page_fault(st struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; - unsigned long address; int write, si_code; + pte_t *pte; + +#ifdef CONFIG_PAX_PAGEEXEC + pmd_t *pmd; + spinlock_t *ptl; + unsigned char pte_mask; +#endif /* get the address */ - address = read_cr2(); + const unsigned long address = read_cr2(); tsk = current; + mm = tsk->mm; si_code = SEGV_MAPERR; @@ -345,14 +384,12 @@ fastcall void __kprobes do_page_fault(st if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); - mm = tsk->mm; - /* * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault.. */ if (in_atomic() || !mm) - goto bad_area_nosemaphore; + goto bad_area_nopax; /* When running in the kernel we expect faults to occur only to * addresses in user space. All other faults represent errors in the @@ -372,10 +409,104 @@ fastcall void __kprobes do_page_fault(st if (!down_read_trylock(&mm->mmap_sem)) { if ((error_code & 4) == 0 && !search_exception_tables(regs->eip)) - goto bad_area_nosemaphore; + goto bad_area_nopax; down_read(&mm->mmap_sem); } +#ifdef CONFIG_PAX_PAGEEXEC + if (nx_enabled || (error_code & 5) != 5 || (regs->eflags & X86_EFLAGS_VM) || + !(mm->pax_flags & MF_PAX_PAGEEXEC)) + goto not_pax_fault; + + /* 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 & 2) && (regs->eip == address))) { + /* instruction fetch attempt from a protected page in user mode */ + up_read(&mm->mmap_sem); + +#ifdef CONFIG_PAX_EMUTRAMP + switch (pax_handle_fetch_fault(regs)) { + case 2: + return; + } +#endif + + pax_report_fault(regs, (void *)regs->eip, (void *)regs->esp); + do_exit(SIGKILL); + } + + pmd = pax_get_pmd(mm, address); + if (unlikely(!pmd)) + goto not_pax_fault; + + pte = pte_offset_map_lock(mm, pmd, address, &ptl); + if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) { + pte_unmap_unlock(pte, ptl); + goto not_pax_fault; + } + + if (unlikely((error_code & 2) && !pte_write(*pte))) { + /* write attempt to a protected page in user mode */ + pte_unmap_unlock(pte, ptl); + goto not_pax_fault; + } + +#ifdef CONFIG_SMP + if (likely(address > get_limit(regs->xcs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask))) +#else + if (likely(address > get_limit(regs->xcs))) +#endif + { + set_pte(pte, pte_mkread(*pte)); + __flush_tlb_one(address); + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return; + } + + pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1)); + + /* + * PaX: fill DTLB with user rights and retry + */ + __asm__ __volatile__ ( +#ifdef CONFIG_PAX_MEMORY_UDEREF + "movw %w4,%%es\n" +#endif + "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,%%es:(%0)\n" + "xorb %3,(%1)\n" +#ifdef CONFIG_PAX_MEMORY_UDEREF + "pushl %%ss\n" + "popl %%es\n" +#endif + : + : "r" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER), "r" (__USER_DS) + : "memory", "cc"); + pte_unmap_unlock(pte, ptl); + up_read(&mm->mmap_sem); + return; + +not_pax_fault: +#endif + vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -393,6 +524,12 @@ fastcall void __kprobes do_page_fault(st if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp) goto bad_area; } + +#ifdef CONFIG_PAX_SEGMEXEC + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end - SEGMEXEC_TASK_SIZE - 1 < address - SEGMEXEC_TASK_SIZE - 1) + goto bad_area; +#endif + if (expand_stack(vma, address)) goto bad_area; /* @@ -402,6 +539,8 @@ fastcall void __kprobes do_page_fault(st good_area: si_code = SEGV_ACCERR; write = 0; + if (nx_enabled && (error_code & 16) && !(vma->vm_flags & VM_EXEC)) + goto bad_area; switch (error_code & 3) { default: /* 3: write, present */ /* fall through */ @@ -457,6 +596,41 @@ bad_area: up_read(&mm->mmap_sem); bad_area_nosemaphore: + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) { + /* + * It's possible to have interrupts off here. + */ + local_irq_enable(); + +#ifdef CONFIG_PAX_PAGEEXEC + if ((nx_enabled && (error_code & 16)) || + ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(error_code & 3) && (regs->eip == address))) { + pax_report_fault(regs, (void *)regs->eip, (void *)regs->esp); + do_exit(SIGKILL); + } +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) { + +#ifdef CONFIG_PAX_EMUTRAMP + switch (pax_handle_fetch_fault(regs)) { + case 2: + return; + } +#endif + + pax_report_fault(regs, (void *)regs->eip, (void *)regs->esp); + do_exit(SIGKILL); + } +#endif + + } +#endif + +bad_area_nopax: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { /* @@ -486,7 +660,7 @@ bad_area_nosemaphore: if (boot_cpu_data.f00f_bug) { unsigned long nr; - nr = (address - idt_descr.address) >> 3; + nr = (address - (unsigned long)idt_descr.address) >> 3; if (nr == 6) { do_invalid_op(regs, 0); @@ -519,18 +693,34 @@ no_context: __typeof__(pte_val(__pte(0))) page; #ifdef CONFIG_X86_PAE - if (error_code & 16) { - pte_t *pte = lookup_address(address); + if (nx_enabled && (error_code & 16)) { + pte = lookup_address(address); if (pte && pte_present(*pte) && !pte_exec_kernel(*pte)) printk(KERN_CRIT "kernel tried to execute " "NX-protected page - exploit attempt? " - "(uid: %d)\n", current->uid); + "(uid: %d, task: %s, pid: %d)\n", + current->uid, current->comm, current->pid); } #endif if (address < PAGE_SIZE) printk(KERN_ALERT "BUG: unable to handle kernel NULL " "pointer dereference"); + +#ifdef CONFIG_PAX_KERNEXEC +#ifdef CONFIG_MODULES + else if (init_mm.start_code <= address && address < (unsigned long)MODULES_END) +#else + else if (init_mm.start_code <= address && address < init_mm.end_code) +#endif + if (tsk->signal->curr_ip) + printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code", + NIPQUAD(tsk->signal->curr_ip), tsk->comm, tsk->pid, tsk->uid, tsk->euid); + else + 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 "BUG: unable to handle kernel paging" " request"); @@ -561,7 +751,7 @@ no_context: * it's allocated already. */ if ((page >> PAGE_SHIFT) < max_low_pfn - && (page & _PAGE_PRESENT)) { + && (page & (_PAGE_PRESENT | _PAGE_PSE)) == _PAGE_PRESENT) { page &= PAGE_MASK; page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)]; @@ -587,7 +777,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (error_code & 4) do_exit(SIGKILL); goto no_context; @@ -646,3 +837,109 @@ void vmalloc_sync_all(void) start = address + PGDIR_SIZE; } } + +#ifdef CONFIG_PAX_EMUTRAMP +/* + * PaX: decide what to do with offenders (regs->eip = fault address) + * + * returns 1 when task should be killed + * 2 when gcc trampoline was detected + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + static const unsigned char trans[8] = { + offsetof(struct pt_regs, eax) / 4, + offsetof(struct pt_regs, ecx) / 4, + offsetof(struct pt_regs, edx) / 4, + offsetof(struct pt_regs, ebx) / 4, + offsetof(struct pt_regs, esp) / 4, + offsetof(struct pt_regs, ebp) / 4, + offsetof(struct pt_regs, esi) / 4, + offsetof(struct pt_regs, edi) / 4, + }; + int err; + + if (regs->eflags & X86_EFLAGS_VM) + return 1; + + if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP)) + return 1; + + do { /* PaX: gcc trampoline emulation #1 */ + unsigned char mov1, mov2; + unsigned short jmp; + unsigned long addr1, addr2; + + err = get_user(mov1, (unsigned char __user *)regs->eip); + err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1)); + err |= get_user(mov2, (unsigned char __user *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6)); + err |= get_user(jmp, (unsigned short __user *)(regs->eip + 10)); + + if (err) + break; + + if ((mov1 & 0xF8) == 0xB8 && + (mov2 & 0xF8) == 0xB8 && + (mov1 & 0x07) != (mov2 & 0x07) && + (jmp & 0xF8FF) == 0xE0FF && + (mov2 & 0x07) == ((jmp>>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; + + err = get_user(mov, (unsigned char __user *)regs->eip); + err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1)); + err |= get_user(jmp, (unsigned char __user *)(regs->eip + 5)); + err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6)); + + if (err) + break; + + if ((mov & 0xF8) == 0xB8 && + jmp == 0xE9) + { + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; + regs->eip += addr2 + 10; + return 2; + } + } while (0); + + return 1; /* PaX in action */ +} +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) +void pax_report_insns(void *pc, void *sp) +{ + long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 20; i++) { + unsigned char c; + if (get_user(c, (unsigned char __user *)pc+i)) + printk("?? "); + else + printk("%02x ", c); + } + printk("\n"); + + printk(KERN_ERR "PAX: bytes at SP-4: "); + for (i = -1; i < 20; i++) { + unsigned long c; + if (get_user(c, (unsigned long __user *)sp+i)) + printk("???????? "); + else + printk("%08lx ", c); + } + printk("\n"); +} +#endif diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/hugetlbpage.c linux-2.6.22.19-g-v/arch/i386/mm/hugetlbpage.c --- linux-2.6.22.19/arch/i386/mm/hugetlbpage.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/hugetlbpage.c 2008-03-04 08:55:59.000000000 +0100 @@ -229,13 +229,18 @@ static unsigned long hugetlb_get_unmappe { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; - unsigned long start_addr; + unsigned long start_addr, task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif if (len > mm->cached_hole_size) { - start_addr = mm->free_area_cache; + start_addr = mm->free_area_cache; } else { - start_addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; + start_addr = mm->mmap_base; + mm->cached_hole_size = 0; } full_search: @@ -243,13 +248,13 @@ full_search: for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { /* At this point: (!vma || addr < vma->vm_end). */ - if (TASK_SIZE - len < addr) { + if (task_size - len < addr) { /* * Start a new search - just in case we missed * some holes. */ - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = TASK_UNMAPPED_BASE; + if (start_addr != mm->mmap_base) { + start_addr = mm->mmap_base; mm->cached_hole_size = 0; goto full_search; } @@ -271,9 +276,8 @@ static unsigned long hugetlb_get_unmappe { struct mm_struct *mm = current->mm; struct vm_area_struct *vma, *prev_vma; - unsigned long base = mm->mmap_base, addr = addr0; + unsigned long base = mm->mmap_base, addr; unsigned long largest_hole = mm->cached_hole_size; - int first_time = 1; /* don't allow allocations above current base */ if (mm->free_area_cache > base) @@ -283,7 +287,7 @@ static unsigned long hugetlb_get_unmappe largest_hole = 0; mm->free_area_cache = base; } -try_again: + /* make sure it can fit in the remaining address space */ if (mm->free_area_cache < len) goto fail; @@ -325,22 +329,26 @@ try_again: fail: /* - * if hint left us with no space for the requested - * mapping then try again: - */ - if (first_time) { - mm->free_area_cache = base; - largest_hole = 0; - first_time = 0; - goto try_again; - } - /* * A failed mmap() very likely causes application failure, * so fall back to the bottom-up function here. This scenario * can happen with large stack limits and large mmap() * allocations. */ - mm->free_area_cache = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE; + else +#endif + + mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + + mm->free_area_cache = mm->mmap_base; mm->cached_hole_size = ~0UL; addr = hugetlb_get_unmapped_area_bottomup(file, addr0, len, pgoff, flags); @@ -348,6 +356,7 @@ fail: /* * Restore the topdown base: */ + mm->mmap_base = base; mm->free_area_cache = base; mm->cached_hole_size = ~0UL; @@ -360,10 +369,17 @@ hugetlb_get_unmapped_area(struct file *f { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; + unsigned long task_size = TASK_SIZE; if (len & ~HPAGE_MASK) return -EINVAL; - if (len > TASK_SIZE) + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif + + if (len > task_size) return -ENOMEM; if (flags & MAP_FIXED) { @@ -375,7 +391,7 @@ hugetlb_get_unmapped_area(struct file *f if (addr) { addr = ALIGN(addr, HPAGE_SIZE); vma = find_vma(mm, addr); - if (TASK_SIZE - len >= addr && + if (task_size - len >= addr && (!vma || addr + len <= vma->vm_start)) return addr; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/init.c linux-2.6.22.19-g-v/arch/i386/mm/init.c --- linux-2.6.22.19/arch/i386/mm/init.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/init.c 2008-03-04 08:55:59.000000000 +0100 @@ -44,6 +44,7 @@ #include #include #include +#include unsigned int __VMALLOC_RESERVE = 128 << 20; @@ -53,32 +54,6 @@ unsigned long highstart_pfn, highend_pfn static int noinline do_test_wp_bit(void); /* - * Creates a middle page table and puts a pointer to it in the - * given global directory entry. This only returns the gd entry - * in non-PAE compilation mode, since the middle layer is folded. - */ -static pmd_t * __init one_md_table_init(pgd_t *pgd) -{ - pud_t *pud; - pmd_t *pmd_table; - -#ifdef CONFIG_X86_PAE - if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { - pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); - - paravirt_alloc_pd(__pa(pmd_table) >> PAGE_SHIFT); - set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); - pud = pud_offset(pgd, 0); - if (pmd_table != pmd_offset(pud, 0)) - BUG(); - } -#endif - pud = pud_offset(pgd, 0); - pmd_table = pmd_offset(pud, 0); - return pmd_table; -} - -/* * Create a page table and place a pointer to it in a middle page * directory entry. */ @@ -88,7 +63,11 @@ static pte_t * __init one_page_table_ini pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT); +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE)); +#else set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); +#endif BUG_ON(page_table != pte_offset_kernel(pmd, 0)); } @@ -109,6 +88,7 @@ static pte_t * __init one_page_table_ini static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; int pgd_idx, pmd_idx; unsigned long vaddr; @@ -119,8 +99,13 @@ static void __init page_table_range_init pgd = pgd_base + pgd_idx; for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { - pmd = one_md_table_init(pgd); - pmd = pmd + pmd_index(vaddr); + pud = pud_offset(pgd, vaddr); + pmd = pmd_offset(pud, vaddr); + +#ifdef CONFIG_X86_PAE + paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT); +#endif + for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) { one_page_table_init(pmd); @@ -130,11 +115,23 @@ static void __init page_table_range_init } } -static inline int is_kernel_text(unsigned long addr) +static inline int is_kernel_text(unsigned long start, unsigned long end) { - if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end) - return 1; - return 0; + unsigned long etext; + +#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) + etext = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET; +#else + etext = (unsigned long)&_etext; +#endif + + if ((start > etext + __KERNEL_TEXT_OFFSET || + end <= (unsigned long)_stext + __KERNEL_TEXT_OFFSET) && + (start > (unsigned long)_einittext + __KERNEL_TEXT_OFFSET || + end <= (unsigned long)_sinittext + __KERNEL_TEXT_OFFSET) && + (start > (unsigned long)__va(0xfffff) || end <= (unsigned long)__va(0xc0000))) + return 0; + return 1; } /* @@ -146,25 +143,29 @@ static void __init kernel_physical_mappi { unsigned long pfn; pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; - int pgd_idx, pmd_idx, pte_ofs; + unsigned int pgd_idx, pmd_idx, pte_ofs; pgd_idx = pgd_index(PAGE_OFFSET); pgd = pgd_base + pgd_idx; pfn = 0; - for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { - pmd = one_md_table_init(pgd); - if (pfn >= max_low_pfn) - continue; + for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) { + pud = pud_offset(pgd, 0); + pmd = pmd_offset(pud, 0); + +#ifdef CONFIG_X86_PAE + paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT); +#endif + for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) { - unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET; + unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET; /* Map with big pages if possible, otherwise create normal page tables. */ - if (cpu_has_pse) { - unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1; - if (is_kernel_text(address) || is_kernel_text(address2)) + if (cpu_has_pse && address >= (unsigned long)__va(0x100000)) { + if (is_kernel_text(address, address + PMD_SIZE)) set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC)); else set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE)); @@ -176,7 +177,7 @@ static void __init kernel_physical_mappi for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++, address += PAGE_SIZE) { - if (is_kernel_text(address)) + if (is_kernel_text(address, address + PAGE_SIZE)) set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); else set_pte(pte, pfn_pte(pfn, PAGE_KERNEL)); @@ -326,9 +327,9 @@ static void __init set_highmem_pages_ini #define set_highmem_pages_init(bad_ppro) do { } while (0) #endif /* CONFIG_HIGHMEM */ -unsigned long long __PAGE_KERNEL = _PAGE_KERNEL; +unsigned long long __PAGE_KERNEL __read_only = _PAGE_KERNEL; EXPORT_SYMBOL(__PAGE_KERNEL); -unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC; +unsigned long long __PAGE_KERNEL_EXEC __read_only = _PAGE_KERNEL_EXEC; #ifdef CONFIG_NUMA extern void __init remap_numa_kva(void); @@ -339,26 +340,10 @@ extern void __init remap_numa_kva(void); void __init native_pagetable_setup_start(pgd_t *base) { #ifdef CONFIG_X86_PAE - int i; - - /* - * Init entries of the first-level page table to the - * zero page, if they haven't already been set up. - * - * In a normal native boot, we'll be running on a - * pagetable rooted in swapper_pg_dir, but not in PAE - * mode, so this will end up clobbering the mappings - * for the lower 24Mbytes of the address space, - * without affecting the kernel address space. - */ - for (i = 0; i < USER_PTRS_PER_PGD; i++) - set_pgd(&base[i], - __pgd(__pa(empty_zero_page) | _PAGE_PRESENT)); + unsigned int i; - /* Make sure kernel address space is empty so that a pagetable - will be allocated for it. */ - memset(&base[USER_PTRS_PER_PGD], 0, - KERNEL_PGD_PTRS * sizeof(pgd_t)); + for (i = 0; i < PTRS_PER_PGD; i++) + paravirt_alloc_pd(__pa(swapper_pm_dir + i) >> PAGE_SHIFT); #else paravirt_alloc_pd(__pa(swapper_pg_dir) >> PAGE_SHIFT); #endif @@ -366,16 +351,6 @@ void __init native_pagetable_setup_start void __init native_pagetable_setup_done(pgd_t *base) { -#ifdef CONFIG_X86_PAE - /* - * Add low memory identity-mappings - SMP needs it when - * starting up on an AP from real-mode. In the non-PAE - * case we already have these mappings through head.S. - * All user-space mappings are explicitly cleared after - * SMP startup. - */ - set_pgd(&base[0], base[USER_PTRS_PER_PGD]); -#endif } /* @@ -437,12 +412,12 @@ static void __init pagetable_init (void) * Swap suspend & friends need this for resume because things like the intel-agp * driver might have split up a kernel 4MB mapping. */ -char __nosavedata swsusp_pg_dir[PAGE_SIZE] +pgd_t __nosavedata swsusp_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned (PAGE_SIZE))); static inline void save_pg_dir(void) { - memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE); + clone_pgd_range(swsusp_pg_dir, swapper_pg_dir, PTRS_PER_PGD); } #else static inline void save_pg_dir(void) @@ -471,8 +446,7 @@ void zap_low_mappings (void) flush_tlb_all(); } -static int disable_nx __initdata = 0; -u64 __supported_pte_mask __read_mostly = ~_PAGE_NX; +u64 __supported_pte_mask __read_only = ~_PAGE_NX; /* * noexec = on|off @@ -482,39 +456,34 @@ u64 __supported_pte_mask __read_mostly = * on Enable * off Disable */ +#if !defined(CONFIG_PAX_PAGEEXEC) static int __init noexec_setup(char *str) { if (!str || !strcmp(str, "on")) { - if (cpu_has_nx) { - __supported_pte_mask |= _PAGE_NX; - disable_nx = 0; - } + if (cpu_has_nx) + nx_enabled = 1; } else if (!strcmp(str,"off")) { - disable_nx = 1; - __supported_pte_mask &= ~_PAGE_NX; + nx_enabled = 0; } else return -EINVAL; return 0; } early_param("noexec", noexec_setup); +#endif int nx_enabled = 0; #ifdef CONFIG_X86_PAE static void __init set_nx(void) { - unsigned int v[4], l, h; + if (!nx_enabled && cpu_has_nx) { + unsigned l, h; - if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) { - cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]); - if ((v[3] & (1 << 20)) && !disable_nx) { - rdmsr(MSR_EFER, l, h); - l |= EFER_NX; - wrmsr(MSR_EFER, l, h); - nx_enabled = 1; - __supported_pte_mask |= _PAGE_NX; - } + __supported_pte_mask &= ~_PAGE_NX; + rdmsr(MSR_EFER, l, h); + l &= ~EFER_NX; + wrmsr(MSR_EFER, l, h); } } @@ -567,14 +536,6 @@ void __init paging_init(void) load_cr3(swapper_pg_dir); -#ifdef CONFIG_X86_PAE - /* - * We will bail out later - printk doesn't work right now so - * the user would just see a hanging kernel. - */ - if (cpu_has_pae) - set_in_cr4(X86_CR4_PAE); -#endif __flush_tlb_all(); kmap_init(); @@ -645,7 +606,7 @@ void __init mem_init(void) 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); @@ -690,10 +651,10 @@ void __init mem_init(void) (unsigned long)&__init_begin, (unsigned long)&__init_end, ((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10, - (unsigned long)&_etext, (unsigned long)&_edata, - ((unsigned long)&_edata - (unsigned long)&_etext) >> 10, + (unsigned long)&_data, (unsigned long)&_edata, + ((unsigned long)&_edata - (unsigned long)&_data) >> 10, - (unsigned long)&_text, (unsigned long)&_etext, + (unsigned long)&_text + __KERNEL_TEXT_OFFSET, (unsigned long)&_etext + __KERNEL_TEXT_OFFSET, ((unsigned long)&_etext - (unsigned long)&_text) >> 10); #ifdef CONFIG_HIGHMEM @@ -704,10 +665,6 @@ void __init mem_init(void) BUG_ON((unsigned long)high_memory > VMALLOC_START); #endif /* double-sanity-check paranoia */ -#ifdef CONFIG_X86_PAE - if (!cpu_has_pae) - panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!"); -#endif if (boot_cpu_data.wp_works_ok < 0) test_wp_bit(); @@ -843,6 +800,38 @@ void free_init_pages(char *what, unsigne void free_initmem(void) { + +#ifdef CONFIG_PAX_KERNEXEC + /* PaX: limit KERNEL_CS to actual size */ + unsigned long addr, limit; + __u32 a, b; + int cpu; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + +#ifdef CONFIG_MODULES + limit = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET; +#else + limit = (unsigned long)&_etext; +#endif + limit = (limit - 1UL) >> PAGE_SHIFT; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + pack_descriptor(&a, &b, get_desc_base(&get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS]), limit, 0x9B, 0xC); + write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_KERNEL_CS, a, b); + } + + /* PaX: make KERNEL_CS read-only */ + for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) { + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); + } + flush_tlb_all(); +#endif + free_init_pages("unused kernel memory", (unsigned long)(&__init_begin), (unsigned long)(&__init_end)); diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/mmap.c linux-2.6.22.19-g-v/arch/i386/mm/mmap.c --- linux-2.6.22.19/arch/i386/mm/mmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/mmap.c 2008-03-04 08:55:59.000000000 +0100 @@ -35,12 +35,18 @@ * Leave an at least ~128 MB hole. */ #define MIN_GAP (128*1024*1024) -#define MAX_GAP (TASK_SIZE/6*5) +#define MAX_GAP (task_size/6*5) static inline unsigned long mmap_base(struct mm_struct *mm) { unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; unsigned long random_factor = 0; + unsigned long task_size = TASK_SIZE; + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif if (current->flags & PF_RANDOMIZE) random_factor = get_random_int() % (1024*1024); @@ -50,7 +56,7 @@ static inline unsigned long mmap_base(st else if (gap > MAX_GAP) gap = MAX_GAP; - return PAGE_ALIGN(TASK_SIZE - gap - random_factor); + return PAGE_ALIGN(task_size - gap - random_factor); } /* @@ -66,11 +72,30 @@ void arch_pick_mmap_layout(struct mm_str if (sysctl_legacy_va_layout || (current->personality & ADDR_COMPAT_LAYOUT) || current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + +#ifdef CONFIG_PAX_SEGMEXEC + if (mm->pax_flags & MF_PAX_SEGMEXEC) + mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE; + else +#endif + mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(mm); + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base -= mm->delta_mmap + mm->delta_stack; +#endif + mm->get_unmapped_area = arch_get_unmapped_area_topdown; mm->unmap_area = arch_unmap_area_topdown; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/mm/pageattr.c linux-2.6.22.19-g-v/arch/i386/mm/pageattr.c --- linux-2.6.22.19/arch/i386/mm/pageattr.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/mm/pageattr.c 2008-03-04 08:55:59.000000000 +0100 @@ -13,6 +13,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(cpa_lock); static struct list_head df_list = LIST_HEAD_INIT(df_list); @@ -37,16 +38,16 @@ pte_t *lookup_address(unsigned long addr } static struct page *split_large_page(unsigned long address, pgprot_t prot, - pgprot_t ref_prot) + pgprot_t ref_prot, unsigned long flags) { int i; unsigned long addr; struct page *base; pte_t *pbase; - spin_unlock_irq(&cpa_lock); + spin_unlock_irqrestore(&cpa_lock, flags); base = alloc_pages(GFP_KERNEL, 0); - spin_lock_irq(&cpa_lock); + spin_lock_irqsave(&cpa_lock, flags); if (!base) return NULL; @@ -99,7 +100,18 @@ static void set_pmd_pte(pte_t *kpte, uns struct page *page; unsigned long flags; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; + + pax_open_kernel(cr0); +#endif + set_pte_atomic(kpte, pte); /* change init_mm */ + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + if (SHARED_KERNEL_PMD) return; @@ -126,7 +138,7 @@ static inline void revert_page(struct pa pte_t *linear; ref_prot = - ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) + ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET) ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE; linear = (pte_t *) @@ -137,7 +149,7 @@ static inline void revert_page(struct pa } static int -__change_page_attr(struct page *page, pgprot_t prot) +__change_page_attr(struct page *page, pgprot_t prot, unsigned long flags) { pte_t *kpte; unsigned long address; @@ -158,13 +170,20 @@ __change_page_attr(struct page *page, pg struct page *split; ref_prot = - ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) + ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET) ? PAGE_KERNEL_EXEC : PAGE_KERNEL; - split = split_large_page(address, prot, ref_prot); + split = split_large_page(address, prot, ref_prot, flags); if (!split) return -ENOMEM; - set_pmd_pte(kpte,address,mk_pte(split, ref_prot)); - kpte_page = split; + if (pte_huge(*kpte)) { + set_pmd_pte(kpte,address,mk_pte(split, ref_prot)); + kpte_page = split; + } else { + __free_pages(split, 0); + kpte = lookup_address(address); + kpte_page = virt_to_page(kpte); + set_pte_atomic(kpte, mk_pte(page, prot)); + } } page_private(kpte_page)++; } else if (!pte_huge(*kpte)) { @@ -216,7 +235,7 @@ int change_page_attr(struct page *page, spin_lock_irqsave(&cpa_lock, flags); for (i = 0; i < numpages; i++, page++) { - err = __change_page_attr(page, prot); + err = __change_page_attr(page, prot, flags); if (err) break; } diff -NurpP --minimal linux-2.6.22.19/arch/i386/oprofile/backtrace.c linux-2.6.22.19-g-v/arch/i386/oprofile/backtrace.c --- linux-2.6.22.19/arch/i386/oprofile/backtrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/oprofile/backtrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -22,7 +22,7 @@ struct frame_head { static struct frame_head * dump_kernel_backtrace(struct frame_head * head) { - oprofile_add_trace(head->ret); + oprofile_add_trace(head->ret + __KERNEL_TEXT_OFFSET); /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ @@ -116,7 +116,7 @@ x86_backtrace(struct pt_regs * const reg head = (struct frame_head *)regs->ebp; #endif - if (!user_mode_vm(regs)) { + if (!user_mode(regs)) { while (depth-- && valid_kernel_stack(head, regs)) head = dump_kernel_backtrace(head); return; diff -NurpP --minimal linux-2.6.22.19/arch/i386/oprofile/op_model_p4.c linux-2.6.22.19-g-v/arch/i386/oprofile/op_model_p4.c --- linux-2.6.22.19/arch/i386/oprofile/op_model_p4.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/oprofile/op_model_p4.c 2008-03-04 08:55:59.000000000 +0100 @@ -47,7 +47,7 @@ static inline void setup_num_counters(vo #endif } -static int inline addr_increment(void) +static inline int addr_increment(void) { #ifdef CONFIG_SMP return smp_num_siblings == 2 ? 2 : 1; diff -NurpP --minimal linux-2.6.22.19/arch/i386/pci/common.c linux-2.6.22.19-g-v/arch/i386/pci/common.c --- linux-2.6.22.19/arch/i386/pci/common.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/pci/common.c 2008-03-04 08:55:59.000000000 +0100 @@ -287,7 +287,7 @@ static struct dmi_system_id __devinitdat DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), }, }, - {} + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL} }; struct pci_bus * __devinit pcibios_scan_root(int busnum) diff -NurpP --minimal linux-2.6.22.19/arch/i386/pci/early.c linux-2.6.22.19-g-v/arch/i386/pci/early.c --- linux-2.6.22.19/arch/i386/pci/early.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/pci/early.c 2008-03-04 08:55:59.000000000 +0100 @@ -7,7 +7,7 @@ /* Direct PCI access. This is used for PCI accesses in early boot before the PCI subsystem works. */ -#define PDprintk(x...) +#define PDprintk(x...) do {} while (0) u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset) { diff -NurpP --minimal linux-2.6.22.19/arch/i386/pci/fixup.c linux-2.6.22.19-g-v/arch/i386/pci/fixup.c --- linux-2.6.22.19/arch/i386/pci/fixup.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/pci/fixup.c 2008-03-04 08:55:59.000000000 +0100 @@ -389,7 +389,7 @@ static struct dmi_system_id __devinitdat DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) diff -NurpP --minimal linux-2.6.22.19/arch/i386/pci/irq.c linux-2.6.22.19-g-v/arch/i386/pci/irq.c --- linux-2.6.22.19/arch/i386/pci/irq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/pci/irq.c 2008-03-04 08:55:59.000000000 +0100 @@ -507,7 +507,7 @@ static __init int intel_router_probe(str static struct pci_device_id __initdata pirq_440gx[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, - { }, + { PCI_DEVICE(0, 0) } }; /* 440GX has a proprietary PIRQ router -- don't use it */ @@ -1049,7 +1049,7 @@ static struct dmi_system_id __initdata p DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; static int __init pcibios_irq_init(void) diff -NurpP --minimal linux-2.6.22.19/arch/i386/pci/pcbios.c linux-2.6.22.19-g-v/arch/i386/pci/pcbios.c --- linux-2.6.22.19/arch/i386/pci/pcbios.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/pci/pcbios.c 2008-03-04 08:55:59.000000000 +0100 @@ -57,50 +57,120 @@ union bios32 { static struct { unsigned long address; unsigned short segment; -} bios32_indirect = { 0, __KERNEL_CS }; +} bios32_indirect __read_only = { 0, __PCIBIOS_CS }; /* * Returns the entry point for the given service, NULL on error */ -static unsigned long bios32_service(unsigned long service) +static unsigned long __devinit bios32_service(unsigned long service) { unsigned char return_code; /* %al */ unsigned long address; /* %ebx */ unsigned long length; /* %ecx */ unsigned long entry; /* %edx */ unsigned long flags; + struct desc_struct *gdt; + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif local_irq_save(flags); - __asm__("lcall *(%%edi); cld" + + gdt = get_cpu_gdt_table(smp_processor_id()); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PCIBIOS_CS].a, + (__u32 *)&gdt[GDT_ENTRY_PCIBIOS_CS].b, + 0UL, 0xFFFFFUL, 0x9B, 0xC); + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PCIBIOS_DS].a, + (__u32 *)&gdt[GDT_ENTRY_PCIBIOS_DS].b, + 0UL, 0xFFFFFUL, 0x93, 0xC); + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + + __asm__("movw %w7, %%ds; lcall *(%%edi); push %%ss; pop %%ds; cld" : "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry) : "0" (service), "1" (0), - "D" (&bios32_indirect)); + "D" (&bios32_indirect), + "r"(__PCIBIOS_DS) + : "memory"); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + gdt[GDT_ENTRY_PCIBIOS_CS].a = 0; + gdt[GDT_ENTRY_PCIBIOS_CS].b = 0; + gdt[GDT_ENTRY_PCIBIOS_DS].a = 0; + gdt[GDT_ENTRY_PCIBIOS_DS].b = 0; + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + local_irq_restore(flags); switch (return_code) { - case 0: - return address + entry; - case 0x80: /* Not present */ - printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); - return 0; - default: /* Shouldn't happen */ - printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", - service, return_code); - return 0; + case 0: { + int cpu; + unsigned char flags; + + printk(KERN_INFO "bios32_service: base:%08lx length:%08lx entry:%08lx\n", address, length, entry); + address = address + PAGE_OFFSET; + length += 16UL; /* some BIOSs underreport this... */ + flags = 4; + if (length >= 64*1024*1024) { + length >>= PAGE_SHIFT; + flags |= 8; + } + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + gdt = get_cpu_gdt_table(cpu); + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PCIBIOS_CS].a, + (__u32 *)&gdt[GDT_ENTRY_PCIBIOS_CS].b, + address, length, 0x9b, flags); + pack_descriptor((__u32 *)&gdt[GDT_ENTRY_PCIBIOS_DS].a, + (__u32 *)&gdt[GDT_ENTRY_PCIBIOS_DS].b, + address, length, 0x93, flags); + } + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + + return entry; + } + case 0x80: /* Not present */ + printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); + return 0; + default: /* Shouldn't happen */ + printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", + service, return_code); + return 0; } } static struct { unsigned long address; unsigned short segment; -} pci_indirect = { 0, __KERNEL_CS }; +} pci_indirect __read_only = { 0, __PCIBIOS_CS }; -static int pci_bios_present; +static int pci_bios_present __read_only; static int __devinit check_pcibios(void) { @@ -109,11 +179,13 @@ static int __devinit check_pcibios(void) unsigned long flags, pcibios_entry; if ((pcibios_entry = bios32_service(PCI_SERVICE))) { - pci_indirect.address = pcibios_entry + PAGE_OFFSET; + pci_indirect.address = pcibios_entry; local_irq_save(flags); - __asm__( - "lcall *(%%edi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%edi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -122,7 +194,8 @@ static int __devinit check_pcibios(void) "=b" (ebx), "=c" (ecx) : "1" (PCIBIOS_PCI_BIOS_PRESENT), - "D" (&pci_indirect) + "D" (&pci_indirect), + "r" (__PCIBIOS_DS) : "memory"); local_irq_restore(flags); @@ -158,7 +231,10 @@ static int __devinit pci_bios_find_devic unsigned short bx; unsigned short ret; - __asm__("lcall *(%%edi); cld\n\t" + __asm__("movw %w7, %%ds\n\t" + "lcall *%%ss:(%%edi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -168,7 +244,8 @@ static int __devinit pci_bios_find_devic "c" (device_id), "d" (vendor), "S" ((int) index), - "D" (&pci_indirect)); + "D" (&pci_indirect), + "r" (__PCIBIOS_DS)); *bus = (bx >> 8) & 0xff; *device_fn = bx & 0xff; return (int) (ret & 0xff00) >> 8; @@ -188,7 +265,10 @@ static int pci_bios_read(unsigned int se switch (len) { case 1: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -197,10 +277,14 @@ static int pci_bios_read(unsigned int se : "1" (PCIBIOS_READ_CONFIG_BYTE), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 2: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -209,10 +293,14 @@ static int pci_bios_read(unsigned int se : "1" (PCIBIOS_READ_CONFIG_WORD), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 4: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -221,7 +309,8 @@ static int pci_bios_read(unsigned int se : "1" (PCIBIOS_READ_CONFIG_DWORD), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; } @@ -244,7 +333,10 @@ static int pci_bios_write(unsigned int s switch (len) { case 1: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -253,10 +345,14 @@ static int pci_bios_write(unsigned int s "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 2: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -265,10 +361,14 @@ static int pci_bios_write(unsigned int s "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; case 4: - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w6, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n\t" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -277,7 +377,8 @@ static int pci_bios_write(unsigned int s "c" (value), "b" (bx), "D" ((long)reg), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); break; } @@ -430,10 +531,13 @@ struct irq_routing_table * __devinit pci DBG("PCI: Fetching IRQ routing table... "); __asm__("push %%es\n\t" + "movw %w8, %%ds\n\t" "push %%ds\n\t" "pop %%es\n\t" - "lcall *(%%esi); cld\n\t" + "lcall *%%ss:(%%esi); cld\n\t" "pop %%es\n\t" + "push %%ss\n\t" + "pop %%ds\n" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -444,7 +548,8 @@ struct irq_routing_table * __devinit pci "1" (0), "D" ((long) &opt), "S" (&pci_indirect), - "m" (opt) + "m" (opt), + "r" (__PCIBIOS_DS) : "memory"); DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map); if (ret & 0xff00) @@ -468,7 +573,10 @@ int pcibios_set_irq_routing(struct pci_d { int ret; - __asm__("lcall *(%%esi); cld\n\t" + __asm__("movw %w5, %%ds\n\t" + "lcall *%%ss:(%%esi); cld\n\t" + "push %%ss\n\t" + "pop %%ds\n" "jc 1f\n\t" "xor %%ah, %%ah\n" "1:" @@ -476,7 +584,8 @@ int pcibios_set_irq_routing(struct pci_d : "0" (PCIBIOS_SET_PCI_HW_INT), "b" ((dev->bus->number << 8) | dev->devfn), "c" ((irq << 8) | (pin + 10)), - "S" (&pci_indirect)); + "S" (&pci_indirect), + "r" (__PCIBIOS_DS)); return !(ret & 0xff00); } EXPORT_SYMBOL(pcibios_set_irq_routing); diff -NurpP --minimal linux-2.6.22.19/arch/i386/power/cpu.c linux-2.6.22.19-g-v/arch/i386/power/cpu.c --- linux-2.6.22.19/arch/i386/power/cpu.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/i386/power/cpu.c 2008-03-04 08:55:59.000000000 +0100 @@ -64,7 +64,7 @@ static void do_fpu_end(void) static void fix_processor_context(void) { int cpu = smp_processor_id(); - struct tss_struct * t = &per_cpu(init_tss, cpu); + struct tss_struct *t = init_tss + cpu; set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ diff -NurpP --minimal linux-2.6.22.19/arch/ia64/Kconfig linux-2.6.22.19-g-v/arch/ia64/Kconfig --- linux-2.6.22.19/arch/ia64/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -592,6 +592,8 @@ endmenu source "arch/ia64/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/ia64/ia32/binfmt_elf32.c linux-2.6.22.19-g-v/arch/ia64/ia32/binfmt_elf32.c --- linux-2.6.22.19/arch/ia64/ia32/binfmt_elf32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/ia32/binfmt_elf32.c 2008-03-04 08:55:59.000000000 +0100 @@ -45,6 +45,13 @@ randomize_stack_top(unsigned long stack_ #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) + +#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#endif + /* Ugly but avoids duplication */ #include "../../../fs/binfmt_elf.c" @@ -226,14 +233,27 @@ ia32_setup_arg_pages (struct linux_binpr mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; else mpnt->vm_flags = VM_STACK_FLAGS; - mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)? - PAGE_COPY_EXEC: PAGE_COPY; + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + mpnt->vm_flags &= ~VM_EXEC; + +#ifdef CONFIG_PAX_MPROTECT + if (current->mm->pax_flags & MF_PAX_MPROTECT) + mpnt->vm_flags &= ~VM_MAYEXEC; +#endif + + } +#endif + + mpnt->vm_page_prot = vm_get_page_prot(mpnt->vm_flags); if ((ret = insert_vm_struct(current->mm, mpnt))) { up_write(¤t->mm->mmap_sem); kmem_cache_free(vm_area_cachep, mpnt); return ret; } - current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt); + vx_vmpages_sub(current->mm, current->mm->total_vm - vma_pages(mpnt)); + current->mm->stack_vm = current->mm->total_vm; } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { diff -NurpP --minimal linux-2.6.22.19/arch/ia64/ia32/ia32_entry.S linux-2.6.22.19-g-v/arch/ia64/ia32/ia32_entry.S --- linux-2.6.22.19/arch/ia64/ia32/ia32_entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/ia32/ia32_entry.S 2008-03-04 08:55:59.000000000 +0100 @@ -446,7 +446,7 @@ ia32_syscall_table: data8 sys_tgkill /* 270 */ data8 compat_sys_utimes data8 sys32_fadvise64_64 - data8 sys_ni_syscall + data8 sys32_vserver data8 sys_ni_syscall data8 sys_ni_syscall /* 275 */ data8 sys_ni_syscall diff -NurpP --minimal linux-2.6.22.19/arch/ia64/ia32/ia32priv.h linux-2.6.22.19-g-v/arch/ia64/ia32/ia32priv.h --- linux-2.6.22.19/arch/ia64/ia32/ia32priv.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/ia32/ia32priv.h 2008-03-04 08:55:59.000000000 +0100 @@ -304,7 +304,14 @@ struct old_linux32_dirent { #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_386 -#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) + #define IA32_GATE_OFFSET IA32_PAGE_OFFSET #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE diff -NurpP --minimal linux-2.6.22.19/arch/ia64/ia32/sys_ia32.c linux-2.6.22.19-g-v/arch/ia64/ia32/sys_ia32.c --- linux-2.6.22.19/arch/ia64/ia32/sys_ia32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/ia32/sys_ia32.c 2008-03-04 08:55:59.000000000 +0100 @@ -1182,7 +1182,7 @@ sys32_gettimeofday (struct compat_timeva { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/asm-offsets.c linux-2.6.22.19-g-v/arch/ia64/kernel/asm-offsets.c --- linux-2.6.22.19/arch/ia64/kernel/asm-offsets.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/asm-offsets.c 2008-03-04 08:55:59.000000000 +0100 @@ -192,6 +192,7 @@ void foo(void) /* for assembly files which can't include sched.h: */ DEFINE(IA64_CLONE_VFORK, CLONE_VFORK); DEFINE(IA64_CLONE_VM, CLONE_VM); + DEFINE(IA64_CLONE_KTHREAD, CLONE_KTHREAD); BLANK(); DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/entry.S linux-2.6.22.19-g-v/arch/ia64/kernel/entry.S --- linux-2.6.22.19/arch/ia64/kernel/entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/entry.S 2008-03-04 08:55:59.000000000 +0100 @@ -1547,7 +1547,7 @@ sys_call_table: data8 sys_mq_notify data8 sys_mq_getsetattr data8 sys_kexec_load - data8 sys_ni_syscall // reserved for vserver + data8 sys_vserver data8 sys_waitid // 1270 data8 sys_add_key data8 sys_request_key diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/module.c linux-2.6.22.19-g-v/arch/ia64/kernel/module.c --- linux-2.6.22.19/arch/ia64/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/module.c 2008-03-04 08:55:59.000000000 +0100 @@ -321,7 +321,7 @@ module_alloc (unsigned long size) void module_free (struct module *mod, void *module_region) { - if (mod->arch.init_unw_table && module_region == mod->module_init) { + if (mod->arch.init_unw_table && module_region == mod->module_init_rx) { unw_remove_unwind_table(mod->arch.init_unw_table); mod->arch.init_unw_table = NULL; } @@ -499,15 +499,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd } static inline int +in_init_rx (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx; +} + +static inline int +in_init_rw (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw; +} + +static inline int in_init (const struct module *mod, uint64_t addr) { - return addr - (uint64_t) mod->module_init < mod->init_size; + return in_init_rx(mod, value) || in_init_rw(mod, value); +} + +static inline int +in_core_rx (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx; +} + +static inline int +in_core_rw (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw; } static inline int in_core (const struct module *mod, uint64_t addr) { - return addr - (uint64_t) mod->module_core < mod->core_size; + return in_core_rx(mod, value) || in_core_rw(mod, value); } static inline int @@ -691,7 +715,14 @@ do_reloc (struct module *mod, uint8_t r_ break; case RV_BDREL: - val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core); + if (in_init_rx(mod, val)) + val -= (uint64_t) mod->module_init_rx; + else if (in_init_rw(mod, val)) + val -= (uint64_t) mod->module_init_rw; + else if (in_core_rx(mod, val)) + val -= (uint64_t) mod->module_core_rx; + else if (in_core_rw(mod, val)) + val -= (uint64_t) mod->module_core_rw; break; case RV_LTV: @@ -825,15 +856,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs, * addresses have been selected... */ uint64_t gp; - if (mod->core_size > MAX_LTOFF) + if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF) /* * This takes advantage of fact that SHF_ARCH_SMALL gets allocated * at the end of the module. */ - gp = mod->core_size - MAX_LTOFF / 2; + gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2; else - gp = mod->core_size / 2; - gp = (uint64_t) mod->module_core + ((gp + 7) & -8); + gp = (mod->core_size_rx + mod->core_size_rw) / 2; + gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8); mod->arch.gp = gp; DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp); } diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/perfmon.c linux-2.6.22.19-g-v/arch/ia64/kernel/perfmon.c --- linux-2.6.22.19/arch/ia64/kernel/perfmon.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/perfmon.c 2008-03-04 08:55:59.000000000 +0100 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -2395,7 +2396,7 @@ pfm_smpl_buffer_alloc(struct task_struct */ insert_vm_struct(mm, vma); - mm->total_vm += size >> PAGE_SHIFT; + vx_vmpages_add(mm, size >> PAGE_SHIFT); vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, vma_pages(vma)); up_write(&task->mm->mmap_sem); diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/process.c linux-2.6.22.19-g-v/arch/ia64/kernel/process.c --- linux-2.6.22.19/arch/ia64/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -105,7 +105,8 @@ show_regs (struct pt_regs *regs) unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri; print_modules(); - printk("\nPid: %d, CPU %d, comm: %20s\n", current->pid, smp_processor_id(), current->comm); + printk("\nPid: %d[#%u], CPU %d, comm: %20s\n", + current->pid, current->xid, smp_processor_id(), current->comm); printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n", regs->cr_ipsr, regs->cr_ifs, ip, print_tainted()); print_symbol("ip is at %s\n", ip); @@ -696,7 +697,8 @@ kernel_thread (int (*fn)(void *), void * regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; regs.sw.pr = (1 << PRED_KERNEL_STACK); - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s.pt, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/ptrace.c linux-2.6.22.19-g-v/arch/ia64/kernel/ptrace.c --- linux-2.6.22.19/arch/ia64/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include @@ -1443,10 +1445,16 @@ sys_ptrace (long request, pid_t pid, uns read_unlock(&tasklist_lock); if (!child) goto out; + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) + goto out_tsk; + ret = -EPERM; 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 -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/sys_ia64.c linux-2.6.22.19-g-v/arch/ia64/kernel/sys_ia64.c --- linux-2.6.22.19/arch/ia64/kernel/sys_ia64.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/sys_ia64.c 2008-03-04 08:55:59.000000000 +0100 @@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil if (REGION_NUMBER(addr) == RGN_HPAGE) addr = 0; #endif + +#ifdef CONFIG_PAX_RANDMMAP + if ((mm->pax_flags & MF_PAX_RANDMMAP) && addr && filp) + addr = mm->free_area_cache; + else +#endif + if (!addr) addr = mm->free_area_cache; @@ -61,9 +68,9 @@ arch_get_unmapped_area (struct file *fil for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { /* At this point: (!vma || addr < vma->vm_end). */ if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) { - if (start_addr != TASK_UNMAPPED_BASE) { + if (start_addr != mm->mmap_base) { /* Start a new search --- just in case we missed some holes. */ - addr = TASK_UNMAPPED_BASE; + addr = mm->mmap_base; goto full_search; } return -ENOMEM; diff -NurpP --minimal linux-2.6.22.19/arch/ia64/kernel/traps.c linux-2.6.22.19-g-v/arch/ia64/kernel/traps.c --- linux-2.6.22.19/arch/ia64/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -60,8 +60,9 @@ die (const char *str, struct pt_regs *re put_cpu(); if (++die.lock_owner_depth < 3) { - printk("%s[%d]: %s %ld [%d]\n", - current->comm, current->pid, str, err, ++die_counter); + printk("%s[%d[#%u]]: %s %ld [%d]\n", + current->comm, current->pid, current->xid, + str, err, ++die_counter); (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); show_regs(regs); } else @@ -313,8 +314,9 @@ handle_fpu_swa (int fp_fault, struct pt_ if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) { last.time = current_jiffies + 5 * HZ; printk(KERN_WARNING - "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n", - current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr); + "%s(%d[#%u]): floating-point assist fault at ip %016lx, isr %016lx\n", + current->comm, current->pid, current->xid, + regs->cr_iip + ia64_psr(regs)->ri, isr); } } } diff -NurpP --minimal linux-2.6.22.19/arch/ia64/mm/fault.c linux-2.6.22.19-g-v/arch/ia64/mm/fault.c --- linux-2.6.22.19/arch/ia64/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -72,6 +74,23 @@ mapped_kernel_page_is_present (unsigned return pte_present(pte); } +#ifdef CONFIG_PAX_PAGEEXEC +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("???????? "); + else + printk("%08x ", c); + } + printk("\n"); +} +#endif + void __kprobes ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { @@ -138,9 +157,23 @@ ia64_do_page_fault (unsigned long addres mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_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 (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip) + goto bad_area; + + up_read(&mm->mmap_sem); + 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 -NurpP --minimal linux-2.6.22.19/arch/ia64/mm/init.c linux-2.6.22.19-g-v/arch/ia64/mm/init.c --- linux-2.6.22.19/arch/ia64/mm/init.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ia64/mm/init.c 2008-03-04 08:55:59.000000000 +0100 @@ -20,8 +20,8 @@ #include #include #include +#include -#include #include #include #include @@ -130,8 +130,21 @@ ia64_init_addr_space (void) vma->vm_mm = current->mm; vma->vm_start = current->thread.rbs_bot & PAGE_MASK; vma->vm_end = vma->vm_start + PAGE_SIZE; - vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7]; vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT; + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + vma->vm_flags &= ~VM_EXEC; + +#ifdef CONFIG_PAX_MPROTECT + if (current->mm->pax_flags & MF_PAX_MPROTECT) + vma->vm_flags &= ~VM_MAYEXEC; +#endif + + } +#endif + + vma->vm_page_prot = vm_get_page_prot(VM_DATA_DEFAULT_FLAGS); down_write(¤t->mm->mmap_sem); if (insert_vm_struct(current->mm, vma)) { up_write(¤t->mm->mmap_sem); diff -NurpP --minimal linux-2.6.22.19/arch/m32r/kernel/process.c linux-2.6.22.19-g-v/arch/m32r/kernel/process.c --- linux-2.6.22.19/arch/m32r/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m32r/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -211,8 +211,8 @@ int kernel_thread(int (*fn)(void *), voi regs.psw = M32R_PSW_BIE; /* Ok, create the new process. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, - NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } /* diff -NurpP --minimal linux-2.6.22.19/arch/m32r/kernel/traps.c linux-2.6.22.19-g-v/arch/m32r/kernel/traps.c --- linux-2.6.22.19/arch/m32r/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m32r/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -195,8 +195,9 @@ static void show_registers(struct pt_reg } else { printk("SPI: %08lx\n", sp); } - printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)", - current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current); + printk("Process %s (pid: %d[#%u], process nr: %d, stackpage=%08lx)", + current->comm, current->pid, current->xid, + 0xffff & i, 4096+(unsigned long)current); /* * When in-kernel, we also print out the stack and code at the diff -NurpP --minimal linux-2.6.22.19/arch/m68k/Kconfig linux-2.6.22.19-g-v/arch/m68k/Kconfig --- linux-2.6.22.19/arch/m68k/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68k/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -678,6 +678,8 @@ source "fs/Kconfig" source "arch/m68k/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/m68k/kernel/process.c linux-2.6.22.19-g-v/arch/m68k/kernel/process.c --- linux-2.6.22.19/arch/m68k/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68k/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -159,7 +159,8 @@ int kernel_thread(int (*fn)(void *), voi { register long retval __asm__ ("d0"); - register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; + register long clone_arg __asm__ ("d1") = + flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD; retval = __NR_clone; __asm__ __volatile__ diff -NurpP --minimal linux-2.6.22.19/arch/m68k/kernel/ptrace.c linux-2.6.22.19-g-v/arch/m68k/kernel/ptrace.c --- linux-2.6.22.19/arch/m68k/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68k/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -278,6 +279,8 @@ long arch_ptrace(struct task_struct *chi ret = ptrace_request(child, request, addr, data); break; } + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) + goto out_tsk; return ret; out_eio: diff -NurpP --minimal linux-2.6.22.19/arch/m68k/kernel/traps.c linux-2.6.22.19-g-v/arch/m68k/kernel/traps.c --- linux-2.6.22.19/arch/m68k/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68k/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -899,8 +899,8 @@ void show_registers(struct pt_regs *regs printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", regs->d4, regs->d5, regs->a0, regs->a1); - printk("Process %s (pid: %d, task=%p)\n", - current->comm, current->pid, current); + printk("Process %s (pid: %d[#%u], task=%p)\n", + current->comm, current->pid, current->xid, current); addr = (unsigned long)&fp->un; printk("Frame format=%X ", regs->format); switch (regs->format) { diff -NurpP --minimal linux-2.6.22.19/arch/m68knommu/Kconfig linux-2.6.22.19-g-v/arch/m68knommu/Kconfig --- linux-2.6.22.19/arch/m68knommu/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68knommu/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -670,6 +670,8 @@ source "fs/Kconfig" source "arch/m68knommu/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/m68knommu/kernel/process.c linux-2.6.22.19-g-v/arch/m68knommu/kernel/process.c --- linux-2.6.22.19/arch/m68knommu/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68knommu/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -122,7 +122,7 @@ void show_regs(struct pt_regs * regs) int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { int retval; - long clone_arg = flags | CLONE_VM; + long clone_arg = flags | CLONE_VM | CLONE_KTHREAD; mm_segment_t fs; fs = get_fs(); diff -NurpP --minimal linux-2.6.22.19/arch/m68knommu/kernel/traps.c linux-2.6.22.19-g-v/arch/m68knommu/kernel/traps.c --- linux-2.6.22.19/arch/m68knommu/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/m68knommu/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -80,8 +80,9 @@ void die_if_kernel(char *str, struct pt_ printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", fp->d4, fp->d5, fp->a0, fp->a1); - printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, PAGE_SIZE+(unsigned long)current); + printk(KERN_EMERG "Process %s (pid: %d[#%u], stackpage=%08lx)\n", + current->comm, current->pid, current->xid, + PAGE_SIZE+(unsigned long)current); show_stack(NULL, (unsigned long *)fp); do_exit(SIGSEGV); } diff -NurpP --minimal linux-2.6.22.19/arch/mips/Kconfig linux-2.6.22.19-g-v/arch/mips/Kconfig --- linux-2.6.22.19/arch/mips/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -1959,6 +1959,8 @@ source "arch/mips/oprofile/Kconfig" source "arch/mips/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/binfmt_elfn32.c linux-2.6.22.19-g-v/arch/mips/kernel/binfmt_elfn32.c --- linux-2.6.22.19/arch/mips/kernel/binfmt_elfn32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/binfmt_elfn32.c 2008-03-04 08:55:59.000000000 +0100 @@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N #undef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE ((current->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) + +#define PAX_DELTA_MMAP_LEN ((current->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#define PAX_DELTA_STACK_LEN ((current->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#endif + #include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/binfmt_elfo32.c linux-2.6.22.19-g-v/arch/mips/kernel/binfmt_elfo32.c --- linux-2.6.22.19/arch/mips/kernel/binfmt_elfo32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/binfmt_elfo32.c 2008-03-04 08:55:59.000000000 +0100 @@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N #undef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE ((current->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) + +#define PAX_DELTA_MMAP_LEN ((current->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#define PAX_DELTA_STACK_LEN ((current->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#endif + #include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/linux32.c linux-2.6.22.19-g-v/arch/mips/kernel/linux32.c --- linux-2.6.22.19/arch/mips/kernel/linux32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/linux32.c 2008-03-04 08:55:59.000000000 +0100 @@ -229,7 +229,7 @@ sys32_gettimeofday(struct compat_timeval { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/process.c linux-2.6.22.19-g-v/arch/mips/kernel/process.c --- linux-2.6.22.19/arch/mips/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -236,7 +236,8 @@ long kernel_thread(int (*fn)(void *), vo #endif /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } /* diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/ptrace.c linux-2.6.22.19-g-v/arch/mips/kernel/ptrace.c --- linux-2.6.22.19/arch/mips/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -171,6 +172,9 @@ long arch_ptrace(struct task_struct *chi { int ret; + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) + goto out; + switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/scall32-o32.S linux-2.6.22.19-g-v/arch/mips/kernel/scall32-o32.S --- linux-2.6.22.19/arch/mips/kernel/scall32-o32.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/scall32-o32.S 2008-03-04 08:55:59.000000000 +0100 @@ -619,7 +619,7 @@ einval: li v0, -EINVAL sys sys_mq_timedreceive 5 sys sys_mq_notify 2 /* 4275 */ sys sys_mq_getsetattr 3 - sys sys_ni_syscall 0 /* sys_vserver */ + sys sys_vserver 3 sys sys_waitid 5 sys sys_ni_syscall 0 /* available, was setaltroot */ sys sys_add_key 5 /* 4280 */ diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/scall64-64.S linux-2.6.22.19-g-v/arch/mips/kernel/scall64-64.S --- linux-2.6.22.19/arch/mips/kernel/scall64-64.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/scall64-64.S 2008-03-04 08:55:59.000000000 +0100 @@ -434,7 +434,7 @@ sys_call_table: PTR sys_mq_timedreceive PTR sys_mq_notify PTR sys_mq_getsetattr /* 5235 */ - PTR sys_ni_syscall /* sys_vserver */ + PTR sys_vserver PTR sys_waitid PTR sys_ni_syscall /* available, was setaltroot */ PTR sys_add_key diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/scall64-n32.S linux-2.6.22.19-g-v/arch/mips/kernel/scall64-n32.S --- linux-2.6.22.19/arch/mips/kernel/scall64-n32.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/scall64-n32.S 2008-03-04 08:55:59.000000000 +0100 @@ -360,7 +360,7 @@ EXPORT(sysn32_call_table) PTR compat_sys_mq_timedreceive PTR compat_sys_mq_notify PTR compat_sys_mq_getsetattr - PTR sys_ni_syscall /* 6240, sys_vserver */ + PTR sys32_vserver /* 6240 */ PTR compat_sys_waitid PTR sys_ni_syscall /* available, was setaltroot */ PTR sys_add_key diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/scall64-o32.S linux-2.6.22.19-g-v/arch/mips/kernel/scall64-o32.S --- linux-2.6.22.19/arch/mips/kernel/scall64-o32.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/scall64-o32.S 2008-03-04 08:55:59.000000000 +0100 @@ -482,7 +482,7 @@ sys_call_table: PTR compat_sys_mq_timedreceive PTR compat_sys_mq_notify /* 4275 */ PTR compat_sys_mq_getsetattr - PTR sys_ni_syscall /* sys_vserver */ + PTR sys32_vserver PTR sys32_waitid PTR sys_ni_syscall /* available, was setaltroot */ PTR sys_add_key /* 4280 */ diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/syscall.c linux-2.6.22.19-g-v/arch/mips/kernel/syscall.c --- linux-2.6.22.19/arch/mips/kernel/syscall.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/syscall.c 2008-03-04 08:55:59.000000000 +0100 @@ -87,6 +87,11 @@ unsigned long arch_get_unmapped_area(str do_color_align = 0; if (filp || (flags & MAP_SHARED)) do_color_align = 1; + +#ifdef CONFIG_PAX_RANDMMAP + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + if (addr) { if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -97,7 +102,7 @@ unsigned long arch_get_unmapped_area(str (!vmm || addr + len <= vmm->vm_start)) return addr; } - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); else diff -NurpP --minimal linux-2.6.22.19/arch/mips/kernel/traps.c linux-2.6.22.19-g-v/arch/mips/kernel/traps.c --- linux-2.6.22.19/arch/mips/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -302,8 +302,9 @@ void show_registers(struct pt_regs *regs { show_regs(regs); print_modules(); - printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", - current->comm, current->pid, current_thread_info(), current); + printk("Process %s (pid: %d:#%u, threadinfo=%p, task=%p)\n", + current->comm, current->pid, current->xid, + current_thread_info(), current); show_stacktrace(current, regs); show_code((unsigned int *) regs->cp0_epc); printk("\n"); diff -NurpP --minimal linux-2.6.22.19/arch/mips/mm/fault.c linux-2.6.22.19-g-v/arch/mips/mm/fault.c --- linux-2.6.22.19/arch/mips/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/mips/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -26,6 +26,23 @@ #include #include /* For VMALLOC_END */ +#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("???????? "); + else + 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 @@ -179,7 +196,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/parisc/Kconfig linux-2.6.22.19-g-v/arch/parisc/Kconfig --- linux-2.6.22.19/arch/parisc/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -271,6 +271,8 @@ source "arch/parisc/oprofile/Kconfig" source "arch/parisc/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/entry.S linux-2.6.22.19-g-v/arch/parisc/kernel/entry.S --- linux-2.6.22.19/arch/parisc/kernel/entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/entry.S 2008-03-04 08:55:59.000000000 +0100 @@ -761,6 +761,7 @@ END(fault_vector_11) #define CLONE_VM 0x100 /* Must agree with */ #define CLONE_UNTRACED 0x00800000 +#define CLONE_KTHREAD 0x10000000 .import do_fork ENTRY(__kernel_thread) diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/module.c linux-2.6.22.19-g-v/arch/parisc/kernel/module.c --- linux-2.6.22.19/arch/parisc/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/module.c 2008-03-04 08:55:59.000000000 +0100 @@ -73,16 +73,38 @@ /* three functions to determine where in the module core * or init pieces the location is */ +static inline int in_init_rx(struct module *me, void *loc) +{ + return (loc >= me->module_init_rx && + loc < (me->module_init_rx + me->init_size_rx)); +} + +static inline int in_init_rw(struct module *me, void *loc) +{ + return (loc >= me->module_init_rw && + loc < (me->module_init_rw + me->init_size_rw)); +} + static inline int in_init(struct module *me, void *loc) { - return (loc >= me->module_init && - loc <= (me->module_init + me->init_size)); + return in_init_rx(me, loc) || in_init_rw(me, loc); +} + +static inline int in_core_rx(struct module *me, void *loc) +{ + return (loc >= me->module_core_rx && + loc < (me->module_core_rx + me->core_size_rx)); +} + +static inline int in_core_rw(struct module *me, void *loc) +{ + return (loc >= me->module_core_rw && + loc < (me->module_core_rw + me->core_size_rw)); } static inline int in_core(struct module *me, void *loc) { - return (loc >= me->module_core && - loc <= (me->module_core + me->core_size)); + return in_core_rx(me, loc) || in_core_rw(me, loc); } static inline int in_local(struct module *me, void *loc) @@ -296,21 +318,21 @@ int module_frob_arch_sections(CONST Elf_ } /* align things a bit */ - me->core_size = ALIGN(me->core_size, 16); - me->arch.got_offset = me->core_size; - me->core_size += gots * sizeof(struct got_entry); + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.got_offset = me->core_size_rw; + me->core_size_rw += gots * sizeof(struct got_entry); - me->core_size = ALIGN(me->core_size, 16); - me->arch.fdesc_offset = me->core_size; - me->core_size += fdescs * sizeof(Elf_Fdesc); + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.fdesc_offset = me->core_size_rw; + me->core_size_rw += fdescs * sizeof(Elf_Fdesc); - me->core_size = ALIGN(me->core_size, 16); - me->arch.stub_offset = me->core_size; - me->core_size += stubs * sizeof(struct stub_entry); + me->core_size_rx = ALIGN(me->core_size_rx, 16); + me->arch.stub_offset = me->core_size_rx; + me->core_size_rx += stubs * sizeof(struct stub_entry); - me->init_size = ALIGN(me->init_size, 16); - me->arch.init_stub_offset = me->init_size; - me->init_size += init_stubs * sizeof(struct stub_entry); + me->init_size_rx = ALIGN(me->init_size_rx, 16); + me->arch.init_stub_offset = me->init_size_rx; + me->init_size_rx += init_stubs * sizeof(struct stub_entry); me->arch.got_max = gots; me->arch.fdesc_max = fdescs; @@ -330,7 +352,7 @@ static Elf64_Word get_got(struct module BUG_ON(value == 0); - got = me->module_core + me->arch.got_offset; + got = me->module_core_rw + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) goto out; @@ -348,7 +370,7 @@ static Elf64_Word get_got(struct module #ifdef CONFIG_64BIT static Elf_Addr get_fdesc(struct module *me, unsigned long value) { - Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; + Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset; if (!value) { printk(KERN_ERR "%s: zero OPD requested!\n", me->name); @@ -366,7 +388,7 @@ static Elf_Addr get_fdesc(struct module /* Create new one */ fdesc->addr = value; - fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; + fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; return (Elf_Addr)fdesc; } #endif /* CONFIG_64BIT */ @@ -386,12 +408,12 @@ static Elf_Addr get_stub(struct module * if(init_section) { i = me->arch.init_stub_count++; BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); - stub = me->module_init + me->arch.init_stub_offset + + stub = me->module_init_rx + me->arch.init_stub_offset + i * sizeof(struct stub_entry); } else { i = me->arch.stub_count++; BUG_ON(me->arch.stub_count > me->arch.stub_max); - stub = me->module_core + me->arch.stub_offset + + stub = me->module_core_rx + me->arch.stub_offset + i * sizeof(struct stub_entry); } @@ -759,7 +781,7 @@ register_unwind_table(struct module *me, table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; end = table + sechdrs[me->arch.unwind_section].sh_size; - gp = (Elf_Addr)me->module_core + me->arch.got_offset; + gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", me->arch.unwind_section, table, end, gp); diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/process.c linux-2.6.22.19-g-v/arch/parisc/kernel/process.c --- linux-2.6.22.19/arch/parisc/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -173,7 +173,7 @@ pid_t kernel_thread(int (*fn)(void *), v * kernel_thread can become a #define. */ - return __kernel_thread(fn, arg, flags); + return __kernel_thread(fn, arg, flags | CLONE_KTHREAD); } EXPORT_SYMBOL(kernel_thread); diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/sys_parisc.c linux-2.6.22.19-g-v/arch/parisc/kernel/sys_parisc.c --- linux-2.6.22.19/arch/parisc/kernel/sys_parisc.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/sys_parisc.c 2008-03-04 08:55:59.000000000 +0100 @@ -111,7 +111,7 @@ unsigned long arch_get_unmapped_area(str if (flags & MAP_FIXED) return addr; if (!addr) - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (filp) { addr = get_shared_area(filp->f_mapping, addr, len, pgoff); diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/sys_parisc32.c linux-2.6.22.19-g-v/arch/parisc/kernel/sys_parisc32.c --- linux-2.6.22.19/arch/parisc/kernel/sys_parisc32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/sys_parisc32.c 2008-03-04 08:55:59.000000000 +0100 @@ -204,11 +204,11 @@ static inline long get_ts32(struct times asmlinkage int sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { - extern void do_gettimeofday(struct timeval *tv); + extern void vx_gettimeofday(struct timeval *tv); if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_compat_timeval(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/syscall_table.S linux-2.6.22.19-g-v/arch/parisc/kernel/syscall_table.S --- linux-2.6.22.19/arch/parisc/kernel/syscall_table.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/syscall_table.S 2008-03-04 08:55:59.000000000 +0100 @@ -363,7 +363,7 @@ ENTRY_COMP(mbind) /* 260 */ ENTRY_COMP(get_mempolicy) ENTRY_COMP(set_mempolicy) - ENTRY_SAME(ni_syscall) /* 263: reserved for vserver */ + ENTRY_DIFF(vserver) ENTRY_SAME(add_key) ENTRY_SAME(request_key) /* 265 */ ENTRY_SAME(keyctl) diff -NurpP --minimal linux-2.6.22.19/arch/parisc/kernel/traps.c linux-2.6.22.19-g-v/arch/parisc/kernel/traps.c --- linux-2.6.22.19/arch/parisc/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -218,8 +218,9 @@ void die_if_kernel(char *str, struct pt_ if (err == 0) return; /* STFU */ - printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n", - current->comm, current->pid, str, err, regs->iaoq[0]); + printk(KERN_CRIT "%s (pid %d:#%u): %s (code %ld) at " RFMT "\n", + current->comm, current->pid, current->xid, + str, err, regs->iaoq[0]); #ifdef PRINT_USER_FAULTS /* XXX for debugging only */ show_regs(regs); @@ -251,8 +252,8 @@ KERN_CRIT " || | pdc_console_restart(); if (err) - printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", - current->comm, current->pid, str, err); + printk(KERN_CRIT "%s (pid %d:#%u): %s (code %ld)\n", + current->comm, current->pid, current->xid, str, err); /* Wot's wrong wif bein' racy? */ if (current->thread.flags & PARISC_KERNEL_DEATH) { @@ -712,9 +713,7 @@ void handle_interruption(int code, struc 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 -NurpP --minimal linux-2.6.22.19/arch/parisc/mm/fault.c linux-2.6.22.19-g-v/arch/parisc/mm/fault.c --- linux-2.6.22.19/arch/parisc/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/parisc/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -53,7 +55,7 @@ DEFINE_PER_CPU(struct exception_data, ex 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) { @@ -139,6 +141,116 @@ parisc_acctyp(unsigned long code, unsign } #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 + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + 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->mm->pax_flags & MF_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("???????? "); + else + printk("%08x ", c); + } + printk("\n"); +} +#endif + void do_page_fault(struct pt_regs *regs, unsigned long code, unsigned long address) { @@ -164,8 +276,33 @@ good_area: 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 ((mm->pax_flags & MF_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_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 @@ -209,8 +346,9 @@ bad_area: #ifdef PRINT_USER_FAULTS printk(KERN_DEBUG "\n"); - printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n", - tsk->pid, tsk->comm, code, address); + printk(KERN_DEBUG "do_page_fault() pid=%d:#%u " + "command='%s' type=%lu address=0x%08lx\n", + tsk->pid, tsk->xid, tsk->comm, code, address); if (vma) { printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n", vma->vm_start, vma->vm_end); @@ -260,7 +398,8 @@ no_context: out_of_memory: up_read(&mm->mmap_sem); - printk(KERN_CRIT "VM: killing process %s\n", current->comm); + printk(KERN_CRIT "VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/Kconfig linux-2.6.22.19-g-v/arch/powerpc/Kconfig --- linux-2.6.22.19/arch/powerpc/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -906,6 +906,8 @@ endmenu source "arch/powerpc/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" config KEYS_COMPAT diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/asm-offsets.c linux-2.6.22.19-g-v/arch/powerpc/kernel/asm-offsets.c --- linux-2.6.22.19/arch/powerpc/kernel/asm-offsets.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/asm-offsets.c 2008-03-04 08:55:59.000000000 +0100 @@ -250,6 +250,7 @@ int main(void) DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + DEFINE(CLONE_KTHREAD, CLONE_KTHREAD); #ifndef CONFIG_PPC64 DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/irq.c linux-2.6.22.19-g-v/arch/powerpc/kernel/irq.c --- linux-2.6.22.19/arch/powerpc/kernel/irq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/irq.c 2008-03-04 08:55:59.000000000 +0100 @@ -53,6 +53,7 @@ #include #include #include +#include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/misc_32.S linux-2.6.22.19-g-v/arch/powerpc/kernel/misc_32.S --- linux-2.6.22.19/arch/powerpc/kernel/misc_32.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/misc_32.S 2008-03-04 08:55:59.000000000 +0100 @@ -745,7 +745,7 @@ _GLOBAL(kernel_thread) mr r30,r3 /* function */ mr r31,r4 /* argument */ ori r3,r5,CLONE_VM /* flags */ - oris r3,r3,CLONE_UNTRACED>>16 + oris r3,r3,(CLONE_UNTRACED|CLONE_KTHREAD)>>16 li r4,0 /* new sp (unused) */ li r0,__NR_clone sc diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/misc_64.S linux-2.6.22.19-g-v/arch/powerpc/kernel/misc_64.S --- linux-2.6.22.19/arch/powerpc/kernel/misc_64.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/misc_64.S 2008-03-04 08:55:59.000000000 +0100 @@ -434,7 +434,7 @@ _GLOBAL(kernel_thread) mr r29,r3 mr r30,r4 ori r3,r5,CLONE_VM /* flags */ - oris r3,r3,(CLONE_UNTRACED>>16) + oris r3,r3,(CLONE_UNTRACED|CLONE_KTHREAD)>>16 li r4,0 /* new sp (unused) */ li r0,__NR_clone sc diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/module_32.c linux-2.6.22.19-g-v/arch/powerpc/kernel/module_32.c --- linux-2.6.22.19/arch/powerpc/kernel/module_32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/module_32.c 2008-03-04 08:55:59.000000000 +0100 @@ -126,7 +126,7 @@ int module_frob_arch_sections(Elf32_Ehdr me->arch.core_plt_section = i; } if (!me->arch.core_plt_section || !me->arch.init_plt_section) { - printk("Module doesn't contain .plt or .init.plt sections.\n"); + printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name); return -ENOEXEC; } @@ -167,11 +167,16 @@ static uint32_t do_plt_call(void *locati DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); /* Init, or core PLT? */ - if (location >= mod->module_core - && location < mod->module_core + mod->core_size) + if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) || + (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw)) entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; - else + else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) || + (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw)) entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; + else { + printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name); + return ~0UL; + } /* Find this entry, or if that fails, the next avail. entry */ while (entry->jump[0]) { diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/process.c linux-2.6.22.19-g-v/arch/powerpc/kernel/process.c --- linux-2.6.22.19/arch/powerpc/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -422,8 +422,9 @@ void show_regs(struct pt_regs * regs) trap = TRAP(regs); if (trap == 0x300 || trap == 0x600) printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p", - current, current->pid, current->comm, task_thread_info(current)); + printk("TASK = %p[%d,#%u] '%s' THREAD: %p", + current, current->pid, current->xid, + current->comm, task_thread_info(current)); #ifdef CONFIG_SMP printk(" CPU: %d", smp_processor_id()); diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/signal_32.c linux-2.6.22.19-g-v/arch/powerpc/kernel/signal_32.c --- linux-2.6.22.19/arch/powerpc/kernel/signal_32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/signal_32.c 2008-03-04 08:55:59.000000000 +0100 @@ -758,7 +758,7 @@ static int handle_rt_signal(unsigned lon /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { + if (vdso32_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { if (save_user_regs(regs, frame, 0)) goto badframe; regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/signal_64.c linux-2.6.22.19-g-v/arch/powerpc/kernel/signal_64.c --- linux-2.6.22.19/arch/powerpc/kernel/signal_64.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/signal_64.c 2008-03-04 08:55:59.000000000 +0100 @@ -400,7 +400,7 @@ static int setup_rt_frame(int signr, str current->thread.fpscr.val = 0; /* Set up to return from userspace. */ - if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { + if (vdso64_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/sys_ppc32.c linux-2.6.22.19-g-v/arch/powerpc/kernel/sys_ppc32.c --- linux-2.6.22.19/arch/powerpc/kernel/sys_ppc32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/sys_ppc32.c 2008-03-04 08:55:59.000000000 +0100 @@ -205,7 +205,7 @@ asmlinkage long compat_sys_gettimeofday( { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/traps.c linux-2.6.22.19-g-v/arch/powerpc/kernel/traps.c --- linux-2.6.22.19/arch/powerpc/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -878,8 +878,9 @@ void nonrecoverable_exception(struct pt_ void trace_syscall(struct pt_regs *regs) { - printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n", - current, current->pid, regs->nip, regs->link, regs->gpr[0], + printk("Task: %p(%d[#%u]), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n", + current, current->pid, current->xid, + regs->nip, regs->link, regs->gpr[0], regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); } diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/kernel/vdso.c linux-2.6.22.19-g-v/arch/powerpc/kernel/vdso.c --- linux-2.6.22.19/arch/powerpc/kernel/vdso.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/kernel/vdso.c 2008-03-04 08:55:59.000000000 +0100 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -199,7 +200,7 @@ int arch_setup_additional_pages(struct l vdso_base = VDSO32_MBASE; #endif - current->mm->context.vdso_base = 0; + current->mm->context.vdso_base = ~0UL; /* vDSO has a problem and was disabled, just don't "enable" it for the * process @@ -216,7 +217,7 @@ int arch_setup_additional_pages(struct l */ down_write(&mm->mmap_sem); vdso_base = get_unmapped_area(NULL, vdso_base, - vdso_pages << PAGE_SHIFT, 0, 0); + vdso_pages << PAGE_SHIFT, 0, MAP_PRIVATE | MAP_EXECUTABLE); if (IS_ERR_VALUE(vdso_base)) { rc = vdso_base; goto fail_mmapsem; diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/mm/fault.c linux-2.6.22.19-g-v/arch/powerpc/mm/fault.c --- linux-2.6.22.19/arch/powerpc/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -29,6 +29,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -62,6 +68,364 @@ static inline int notify_page_fault(stru } #endif +#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 int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + memset(vma, 0, sizeof(*vma)); + 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 = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} +#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 sigreturn trampoline was detected + * 6 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_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, GFP_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; + } + + if (pax_insert_vma(vma, call_syscall)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + current->mm->call_syscall = call_syscall; + up_write(¤t->mm->mmap_sem); + +emulate: + regs->gpr[PT_R0] = __NR_sigreturn; + regs->nip = call_syscall; + return 5; + } + } 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, GFP_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; + } + + if (pax_insert_vma(vma, call_syscall)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + 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 6; + } + } 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("???????? "); + else + 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. @@ -157,7 +521,7 @@ int __kprobes do_page_fault(struct pt_re * indicate errors in DSISR but can validly be set in SRR1. */ if (trap == 0x400) - error_code &= 0x48200000; + error_code &= 0x58200000; else is_write = error_code & DSISR_ISSTORE; #else @@ -355,6 +719,37 @@ bad_area: bad_area_nosemaphore: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_PAX_PAGEEXEC) { +#ifdef CONFIG_PPC64 + if (is_exec && (error_code & DSISR_PROTFAULT)) { +#else + if (is_exec && regs->nip == address) { +#endif + switch (pax_handle_fetch_fault(regs)) { + +#ifdef CONFIG_PAX_EMUPLT + case 2: + case 3: + case 4: + return 0; +#endif + +#ifdef CONFIG_PAX_EMUSIGRT + case 5: + case 6: + return 0; +#endif + + } + + pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[PT_R1]); + do_exit(SIGKILL); + } + } +#endif + _exception(SIGSEGV, regs, code, address); return 0; } @@ -378,7 +773,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", current->comm); + printk("VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); if (user_mode(regs)) do_exit(SIGKILL); return SIGKILL; diff -NurpP --minimal linux-2.6.22.19/arch/powerpc/mm/mmap.c linux-2.6.22.19-g-v/arch/powerpc/mm/mmap.c --- linux-2.6.22.19/arch/powerpc/mm/mmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/powerpc/mm/mmap.c 2008-03-04 08:55:59.000000000 +0100 @@ -75,10 +75,22 @@ void arch_pick_mmap_layout(struct mm_str */ if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base -= mm->delta_mmap + mm->delta_stack; +#endif + mm->get_unmapped_area = arch_get_unmapped_area_topdown; mm->unmap_area = arch_unmap_area_topdown; } diff -NurpP --minimal linux-2.6.22.19/arch/ppc/Kconfig linux-2.6.22.19-g-v/arch/ppc/Kconfig --- linux-2.6.22.19/arch/ppc/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ppc/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -1455,6 +1455,8 @@ source "arch/powerpc/oprofile/Kconfig" source "arch/ppc/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/ppc/kernel/asm-offsets.c linux-2.6.22.19-g-v/arch/ppc/kernel/asm-offsets.c --- linux-2.6.22.19/arch/ppc/kernel/asm-offsets.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ppc/kernel/asm-offsets.c 2008-03-04 08:55:59.000000000 +0100 @@ -120,6 +120,7 @@ main(void) DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + DEFINE(CLONE_KTHREAD, CLONE_KTHREAD); DEFINE(MM_PGD, offsetof(struct mm_struct, pgd)); /* About the CPU features table */ diff -NurpP --minimal linux-2.6.22.19/arch/ppc/kernel/misc.S linux-2.6.22.19-g-v/arch/ppc/kernel/misc.S --- linux-2.6.22.19/arch/ppc/kernel/misc.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ppc/kernel/misc.S 2008-03-04 08:55:59.000000000 +0100 @@ -848,7 +848,7 @@ _GLOBAL(kernel_thread) mr r30,r3 /* function */ mr r31,r4 /* argument */ ori r3,r5,CLONE_VM /* flags */ - oris r3,r3,CLONE_UNTRACED>>16 + oris r3,r3,(CLONE_UNTRACED|CLONE_KTHREAD)>>16 li r4,0 /* new sp (unused) */ li r0,__NR_clone sc diff -NurpP --minimal linux-2.6.22.19/arch/ppc/kernel/traps.c linux-2.6.22.19-g-v/arch/ppc/kernel/traps.c --- linux-2.6.22.19/arch/ppc/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ppc/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -696,8 +696,9 @@ void nonrecoverable_exception(struct pt_ void trace_syscall(struct pt_regs *regs) { - printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n", - current, current->pid, regs->nip, regs->link, regs->gpr[0], + printk("Task: %p(%d[#%u]), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld %s\n", + current, current->pid, current->xid, + regs->nip, regs->link, regs->gpr[0], regs->ccr&0x10000000?"Error=":"", regs->gpr[3], print_tainted()); } diff -NurpP --minimal linux-2.6.22.19/arch/ppc/mm/fault.c linux-2.6.22.19-g-v/arch/ppc/mm/fault.c --- linux-2.6.22.19/arch/ppc/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/ppc/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -25,6 +25,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -48,6 +53,364 @@ unsigned long pte_misses; /* updated by unsigned long pte_errors; /* updated by do_page_fault() */ unsigned int probingmem; +#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 int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + memset(vma, 0, sizeof(*vma)); + 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 = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} +#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 sigreturn trampoline was detected + * 6 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_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, GFP_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; + } + + if (pax_insert_vma(vma, call_syscall)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + current->mm->call_syscall = call_syscall; + up_write(¤t->mm->mmap_sem); + +emulate: + regs->gpr[PT_R0] = __NR_sigreturn; + regs->nip = call_syscall; + return 5; + } + } 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, GFP_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; + } + + if (pax_insert_vma(vma, call_syscall)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + 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 6; + } + } 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("???????? "); + else + 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. @@ -108,7 +471,7 @@ int do_page_fault(struct pt_regs *regs, * 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 || CONFIG_BOOKE */ @@ -203,15 +566,14 @@ good_area: pte_t *ptep; pmd_t *pmdp; -#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/Book-E supports per-page execute permission, * we lazily flush dcache to icache. */ ptep = NULL; @@ -234,6 +596,7 @@ good_area: pte_unmap_unlock(ptep, ptl); } #endif +#endif /* a read */ } else { /* protection fault */ @@ -279,6 +642,33 @@ bad_area: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_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 0; +#endif + +#ifdef CONFIG_PAX_EMUSIGRT + case 5: + case 6: + return 0; +#endif + + } + + pax_report_fault(regs, (void *)regs->nip, (void *)regs->gpr[1]); + do_exit(SIGKILL); + } + } +#endif + _exception(SIGSEGV, regs, code, address); return 0; } @@ -296,7 +686,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", current->comm); + printk("VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); if (user_mode(regs)) do_exit(SIGKILL); return SIGKILL; diff -NurpP --minimal linux-2.6.22.19/arch/s390/Kconfig linux-2.6.22.19-g-v/arch/s390/Kconfig --- linux-2.6.22.19/arch/s390/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -551,6 +551,8 @@ endmenu source "arch/s390/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/s390/kernel/compat_linux.c linux-2.6.22.19-g-v/arch/s390/kernel/compat_linux.c --- linux-2.6.22.19/arch/s390/kernel/compat_linux.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/kernel/compat_linux.c 2008-03-04 08:55:59.000000000 +0100 @@ -567,7 +567,7 @@ asmlinkage long sys32_gettimeofday(struc { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/s390/kernel/module.c linux-2.6.22.19-g-v/arch/s390/kernel/module.c --- linux-2.6.22.19/arch/s390/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/kernel/module.c 2008-03-04 08:55:59.000000000 +0100 @@ -166,11 +166,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr, /* Increase core size by size of got & plt and set start offsets for got and plt. */ - me->core_size = ALIGN(me->core_size, 4); - me->arch.got_offset = me->core_size; - me->core_size += me->arch.got_size; - me->arch.plt_offset = me->core_size; - me->core_size += me->arch.plt_size; + me->core_size_rw = ALIGN(me->core_size_rw, 4); + me->arch.got_offset = me->core_size_rw; + me->core_size_rw += me->arch.got_size; + me->arch.plt_offset = me->core_size_rx; + me->core_size_rx += me->arch.plt_size; return 0; } @@ -256,7 +256,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base if (info->got_initialized == 0) { Elf_Addr *gotent; - gotent = me->module_core + me->arch.got_offset + + gotent = me->module_core_rw + me->arch.got_offset + info->got_offset; *gotent = val; info->got_initialized = 1; @@ -280,7 +280,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base else if (r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT) *(unsigned int *) loc = - (val + (Elf_Addr) me->module_core - loc) >> 1; + (val + (Elf_Addr) me->module_core_rw - loc) >> 1; else if (r_type == R_390_GOT64 || r_type == R_390_GOTPLT64) *(unsigned long *) loc = val; @@ -294,7 +294,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ if (info->plt_initialized == 0) { unsigned int *ip; - ip = me->module_core + me->arch.plt_offset + + ip = me->module_core_rx + me->arch.plt_offset + info->plt_offset; #ifndef CONFIG_64BIT ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ @@ -316,7 +316,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base val = me->arch.plt_offset - me->arch.got_offset + info->plt_offset + rela->r_addend; else - val = (Elf_Addr) me->module_core + + val = (Elf_Addr) me->module_core_rx + me->arch.plt_offset + info->plt_offset + rela->r_addend - loc; if (r_type == R_390_PLT16DBL) @@ -336,7 +336,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base case R_390_GOTOFF32: /* 32 bit offset to GOT. */ case R_390_GOTOFF64: /* 64 bit offset to GOT. */ val = val + rela->r_addend - - ((Elf_Addr) me->module_core + me->arch.got_offset); + ((Elf_Addr) me->module_core_rw + me->arch.got_offset); if (r_type == R_390_GOTOFF16) *(unsigned short *) loc = val; else if (r_type == R_390_GOTOFF32) @@ -346,7 +346,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base break; case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */ - val = (Elf_Addr) me->module_core + me->arch.got_offset + + val = (Elf_Addr) me->module_core_rw + me->arch.got_offset + rela->r_addend - loc; if (r_type == R_390_GOTPC) *(unsigned int *) loc = val; diff -NurpP --minimal linux-2.6.22.19/arch/s390/kernel/process.c linux-2.6.22.19-g-v/arch/s390/kernel/process.c --- linux-2.6.22.19/arch/s390/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -164,9 +164,9 @@ void show_regs(struct pt_regs *regs) struct task_struct *tsk = current; printk("CPU: %d %s\n", task_thread_info(tsk)->cpu, print_tainted()); - printk("Process %s (pid: %d, task: %p, ksp: %p)\n", - current->comm, current->pid, (void *) tsk, - (void *) tsk->thread.ksp); + printk("Process %s (pid: %d[#%u], task: %p, ksp: %p)\n", + current->comm, current->pid, current->xid, + (void *) tsk, (void *) tsk->thread.ksp); show_registers(regs); /* Show stack backtrace if pt_regs is from kernel mode */ @@ -197,7 +197,7 @@ int kernel_thread(int (*fn)(void *), voi regs.orig_gpr2 = -1; /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, 0, ®s, 0, NULL, NULL); } diff -NurpP --minimal linux-2.6.22.19/arch/s390/kernel/ptrace.c linux-2.6.22.19-g-v/arch/s390/kernel/ptrace.c --- linux-2.6.22.19/arch/s390/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -725,7 +726,13 @@ sys_ptrace(long request, long pid, long goto out; } + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) { + ret = -EPERM; + goto out_tsk; + } + ret = do_ptrace(child, request, addr, data); +out_tsk: put_task_struct(child); out: unlock_kernel(); diff -NurpP --minimal linux-2.6.22.19/arch/s390/kernel/syscalls.S linux-2.6.22.19-g-v/arch/s390/kernel/syscalls.S --- linux-2.6.22.19/arch/s390/kernel/syscalls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/kernel/syscalls.S 2008-03-04 08:55:59.000000000 +0100 @@ -271,7 +271,7 @@ SYSCALL(sys_clock_settime,sys_clock_sett SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper) /* 260 */ SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper) SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper) -NI_SYSCALL /* reserved for vserver */ +SYSCALL(sys_vserver,sys_vserver,sys32_vserver) SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper) SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper) SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper) diff -NurpP --minimal linux-2.6.22.19/arch/s390/mm/fault.c linux-2.6.22.19-g-v/arch/s390/mm/fault.c --- linux-2.6.22.19/arch/s390/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/s390/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -216,7 +216,8 @@ static int do_out_of_memory(struct pt_re down_read(&mm->mmap_sem); return 1; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (regs->psw.mask & PSW_MASK_PSTATE) do_exit(SIGKILL); do_no_context(regs, error_code, address); diff -NurpP --minimal linux-2.6.22.19/arch/sh/Kconfig linux-2.6.22.19-g-v/arch/sh/Kconfig --- linux-2.6.22.19/arch/sh/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -723,6 +723,8 @@ source "arch/sh/oprofile/Kconfig" source "arch/sh/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/sh/kernel/irq.c linux-2.6.22.19-g-v/arch/sh/kernel/irq.c --- linux-2.6.22.19/arch/sh/kernel/irq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh/kernel/irq.c 2008-03-04 08:55:59.000000000 +0100 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/sh/kernel/process.c linux-2.6.22.19-g-v/arch/sh/kernel/process.c --- linux-2.6.22.19/arch/sh/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -118,7 +118,8 @@ void machine_power_off(void) void show_regs(struct pt_regs * regs) { printk("\n"); - printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); + printk("Pid : %d:#%u, Comm: %20s\n", + current->pid, current->xid, current->comm); print_symbol("PC is at %s\n", instruction_pointer(regs)); printk("PC : %08lx SP : %08lx SR : %08lx ", regs->pc, regs->regs[15], regs->sr); @@ -179,7 +180,7 @@ int kernel_thread(int (*fn)(void *), voi regs.sr = (1 << 30); /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, 0, ®s, 0, NULL, NULL); } diff -NurpP --minimal linux-2.6.22.19/arch/sh/kernel/vsyscall/vsyscall.c linux-2.6.22.19-g-v/arch/sh/kernel/vsyscall/vsyscall.c --- linux-2.6.22.19/arch/sh/kernel/vsyscall/vsyscall.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh/kernel/vsyscall/vsyscall.c 2008-03-04 08:55:59.000000000 +0100 @@ -18,6 +18,7 @@ #include #include #include +#include /* * Should the kernel map a VDSO page into processes and pass its diff -NurpP --minimal linux-2.6.22.19/arch/sh/mm/fault.c linux-2.6.22.19-g-v/arch/sh/mm/fault.c --- linux-2.6.22.19/arch/sh/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -201,7 +201,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/sh64/kernel/process.c linux-2.6.22.19-g-v/arch/sh64/kernel/process.c --- linux-2.6.22.19/arch/sh64/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh64/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -400,8 +400,8 @@ int kernel_thread(int (*fn)(void *), voi regs.pc = (unsigned long)kernel_thread_helper; regs.sr = (1 << 30); - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); + return do_fork(flags | CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD, + 0, ®s, 0, NULL, NULL); } /* diff -NurpP --minimal linux-2.6.22.19/arch/sh64/mm/fault.c linux-2.6.22.19-g-v/arch/sh64/mm/fault.c --- linux-2.6.22.19/arch/sh64/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sh64/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -81,7 +81,7 @@ static inline void print_vma(struct vm_a static inline void print_task(struct task_struct *tsk) { - printk("Task pid %d\n", tsk->pid); + printk("Task pid %d:#%u\n", tsk->pid, tsk->xid); } static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address) @@ -330,7 +330,8 @@ out_of_memory: down_read(&mm->mmap_sem); goto survive; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (user_mode(regs)) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/sparc/Kconfig linux-2.6.22.19-g-v/arch/sparc/Kconfig --- linux-2.6.22.19/arch/sparc/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -317,6 +317,8 @@ endmenu source "arch/sparc/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/sparc/Makefile linux-2.6.22.19-g-v/arch/sparc/Makefile --- linux-2.6.22.19/arch/sparc/Makefile 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/Makefile 2008-03-04 08:55:59.000000000 +0100 @@ -36,7 +36,7 @@ drivers-$(CONFIG_OPROFILE) += arch/sparc # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-) INIT_Y := $(patsubst %/, %/built-in.o, $(init-y)) CORE_Y := $(core-y) -CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/ CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y)) DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y)) NET_Y := $(patsubst %/, %/built-in.o, $(net-y)) diff -NurpP --minimal linux-2.6.22.19/arch/sparc/kernel/process.c linux-2.6.22.19-g-v/arch/sparc/kernel/process.c --- linux-2.6.22.19/arch/sparc/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -705,7 +705,8 @@ pid_t kernel_thread(int (*fn)(void *), v /* Notreached by child. */ "1: mov %%o0, %0\n\t" : "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), + "i" (__NR_clone), "r" (flags | + CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD), "i" (__NR_exit), "r" (fn), "r" (arg) : "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; diff -NurpP --minimal linux-2.6.22.19/arch/sparc/kernel/ptrace.c linux-2.6.22.19-g-v/arch/sparc/kernel/ptrace.c --- linux-2.6.22.19/arch/sparc/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -302,6 +304,15 @@ asmlinkage void do_ptrace(struct pt_regs pt_error_return(regs, -ret); goto out; } + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) { + pt_error_return(regs, ESRCH); + goto out_tsk; + } + + 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)) { diff -NurpP --minimal linux-2.6.22.19/arch/sparc/kernel/sys_sparc.c linux-2.6.22.19-g-v/arch/sparc/kernel/sys_sparc.c --- linux-2.6.22.19/arch/sparc/kernel/sys_sparc.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/kernel/sys_sparc.c 2008-03-04 08:55:59.000000000 +0100 @@ -57,7 +57,7 @@ unsigned long arch_get_unmapped_area(str if (ARCH_SUN4C_SUN4 && len > 0x20000000) return -ENOMEM; if (!addr) - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (flags & MAP_SHARED) addr = COLOUR_ALIGN(addr); diff -NurpP --minimal linux-2.6.22.19/arch/sparc/kernel/systbls.S linux-2.6.22.19-g-v/arch/sparc/kernel/systbls.S --- linux-2.6.22.19/arch/sparc/kernel/systbls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/kernel/systbls.S 2008-03-04 08:55:59.000000000 +0100 @@ -71,7 +71,7 @@ sys_call_table: /*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl /*255*/ .long sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun -/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy +/*265*/ .long sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid /*280*/ .long sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat diff -NurpP --minimal linux-2.6.22.19/arch/sparc/kernel/traps.c linux-2.6.22.19-g-v/arch/sparc/kernel/traps.c --- linux-2.6.22.19/arch/sparc/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -99,7 +99,8 @@ void die_if_kernel(char *str, struct pt_ " /_| \\__/ |_\\\n" " \\__U_/\n"); - printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); + printk("%s(%d[#%u]): %s [#%d]\n", current->comm, + current->pid, current->xid, str, ++die_counter); show_regs(regs); __SAVE; __SAVE; __SAVE; __SAVE; diff -NurpP --minimal linux-2.6.22.19/arch/sparc/mm/fault.c linux-2.6.22.19-g-v/arch/sparc/mm/fault.c --- linux-2.6.22.19/arch/sparc/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -21,6 +21,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -216,6 +220,252 @@ static unsigned long compute_si_addr(str return safe_compute_effective_address(regs, insn); } +#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 int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + memset(vma, 0, sizeof(*vma)); + 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 = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} + +/* + * 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 + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + 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 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); + 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, GFP_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; + } + + if (pax_insert_vma(vma, call_dl_resolve)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + 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("???????? "); + else + printk("%08x ", c); + } + printk("\n"); +} +#endif + asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address) { @@ -279,6 +529,24 @@ good_area: if(!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { + +#ifdef CONFIG_PAX_PAGEEXEC + if ((mm->pax_flags & MF_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 + + } + 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; @@ -367,7 +635,8 @@ no_context: */ out_of_memory: up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (from_user) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/sparc/mm/init.c linux-2.6.22.19-g-v/arch/sparc/mm/init.c --- linux-2.6.22.19/arch/sparc/mm/init.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/mm/init.c 2008-03-04 08:55:59.000000000 +0100 @@ -333,17 +333,17 @@ void __init paging_init(void) /* 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 -NurpP --minimal linux-2.6.22.19/arch/sparc/mm/srmmu.c linux-2.6.22.19-g-v/arch/sparc/mm/srmmu.c --- linux-2.6.22.19/arch/sparc/mm/srmmu.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc/mm/srmmu.c 2008-03-04 08:55:59.000000000 +0100 @@ -2160,6 +2160,13 @@ void __init ld_mmu_srmmu(void) 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); diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/Kconfig linux-2.6.22.19-g-v/arch/sparc64/Kconfig --- linux-2.6.22.19/arch/sparc64/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -451,6 +451,8 @@ endmenu source "arch/sparc64/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/Makefile linux-2.6.22.19-g-v/arch/sparc64/kernel/Makefile --- linux-2.6.22.19/arch/sparc64/kernel/Makefile 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/Makefile 2008-03-04 08:55:59.000000000 +0100 @@ -3,7 +3,7 @@ # EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror +#EXTRA_CFLAGS := -Werror extra-y := head.o init_task.o vmlinux.lds diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/binfmt_aout32.c linux-2.6.22.19-g-v/arch/sparc64/kernel/binfmt_aout32.c --- linux-2.6.22.19/arch/sparc64/kernel/binfmt_aout32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/binfmt_aout32.c 2008-03-04 08:55:59.000000000 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/process.c linux-2.6.22.19-g-v/arch/sparc64/kernel/process.c --- linux-2.6.22.19/arch/sparc64/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -707,7 +707,8 @@ pid_t kernel_thread(int (*fn)(void *), v /* Notreached by child. */ "1:" : "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), + "i" (__NR_clone), "r" (flags | + CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD), "i" (__NR_exit), "r" (fn), "r" (arg) : "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/ptrace.c linux-2.6.22.19-g-v/arch/sparc64/kernel/ptrace.c --- linux-2.6.22.19/arch/sparc64/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -215,6 +217,15 @@ asmlinkage void do_ptrace(struct pt_regs pt_error_return(regs, -ret); goto out; } + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) { + pt_error_return(regs, ESRCH); + goto out_tsk; + } + + 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)) { diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/sys_sparc.c linux-2.6.22.19-g-v/arch/sparc64/kernel/sys_sparc.c --- linux-2.6.22.19/arch/sparc64/kernel/sys_sparc.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/sys_sparc.c 2008-03-04 08:55:59.000000000 +0100 @@ -124,7 +124,7 @@ unsigned long arch_get_unmapped_area(str /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && + if ((filp || (flags & MAP_SHARED)) && ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; @@ -139,6 +139,10 @@ unsigned long arch_get_unmapped_area(str if (filp || (flags & MAP_SHARED)) do_color_align = 1; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + if (addr) { if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -152,9 +156,9 @@ unsigned long arch_get_unmapped_area(str } if (len > mm->cached_hole_size) { - start_addr = addr = mm->free_area_cache; + start_addr = addr = mm->free_area_cache; } else { - start_addr = addr = TASK_UNMAPPED_BASE; + start_addr = addr = mm->mmap_base; mm->cached_hole_size = 0; } @@ -174,8 +178,8 @@ full_search: vma = find_vma(mm, VA_EXCLUDE_END); } if (unlikely(task_size < addr)) { - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; + if (start_addr != mm->mmap_base) { + start_addr = addr = mm->mmap_base; mm->cached_hole_size = 0; goto full_search; } @@ -215,7 +219,7 @@ arch_get_unmapped_area_topdown(struct fi /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ - if ((flags & MAP_SHARED) && + if ((filp || (flags & MAP_SHARED)) && ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; @@ -378,6 +382,12 @@ void arch_pick_mmap_layout(struct mm_str current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY || sysctl_legacy_va_layout) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { @@ -392,6 +402,12 @@ void arch_pick_mmap_layout(struct mm_str gap = (task_size / 6 * 5); mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor); + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base -= mm->delta_mmap + mm->delta_stack; +#endif + mm->get_unmapped_area = arch_get_unmapped_area_topdown; mm->unmap_area = arch_unmap_area_topdown; } diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/sys_sparc32.c linux-2.6.22.19-g-v/arch/sparc64/kernel/sys_sparc32.c --- linux-2.6.22.19/arch/sparc64/kernel/sys_sparc32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/sys_sparc32.c 2008-03-04 08:55:59.000000000 +0100 @@ -729,7 +729,7 @@ asmlinkage long sys32_gettimeofday(struc { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/systbls.S linux-2.6.22.19-g-v/arch/sparc64/kernel/systbls.S --- linux-2.6.22.19/arch/sparc64/kernel/systbls.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/systbls.S 2008-03-04 08:55:59.000000000 +0100 @@ -72,7 +72,7 @@ sys_call_table32: /*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl .word sys32_sync_file_range, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun - .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy + .word sys_timer_delete, compat_sys_timer_create, sys32_vserver, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid /*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat @@ -144,7 +144,7 @@ sys_call_table: /*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun - .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy + .word sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid /*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/kernel/traps.c linux-2.6.22.19-g-v/arch/sparc64/kernel/traps.c --- linux-2.6.22.19/arch/sparc64/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -2225,7 +2225,8 @@ void die_if_kernel(char *str, struct pt_ " /_| \\__/ |_\\\n" " \\__U_/\n"); - printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); + printk("%s(%d[#%u]): %s [#%d]\n", current->comm, + current->pid, current->xid, str, ++die_counter); notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); __asm__ __volatile__("flushw"); __show_regs(regs); diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/mm/Makefile linux-2.6.22.19-g-v/arch/sparc64/mm/Makefile --- linux-2.6.22.19/arch/sparc64/mm/Makefile 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/mm/Makefile 2008-03-04 08:55:59.000000000 +0100 @@ -3,7 +3,7 @@ # EXTRA_AFLAGS := -ansi -EXTRA_CFLAGS := -Werror +#EXTRA_CFLAGS := -Werror obj-y := ultra.o tlb.o tsb.o fault.o init.o generic.o diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/mm/fault.c linux-2.6.22.19-g-v/arch/sparc64/mm/fault.c --- linux-2.6.22.19/arch/sparc64/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -20,6 +20,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -270,6 +274,369 @@ cannot_handle: 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 int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) +{ + int ret; + + memset(vma, 0, sizeof(*vma)); + 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 = vm_get_page_prot(vma->vm_flags); + vma->vm_ops = &pax_vm_ops; + + ret = insert_vm_struct(current->mm, vma); + if (ret) + return ret; + + ++current->mm->total_vm; + return 0; +} +#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 + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + 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 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); + 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: patched PLT emulation #7 */ + 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 & 0xFFF00000U) == 0x30600000U && + nop == 0x01000000U) + { + unsigned long addr; + + addr = (sethi & 0x003FFFFFU) << 10; + regs->u_regs[UREG_G1] = addr; + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); + 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, GFP_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; + } + + if (pax_insert_vma(vma, call_dl_resolve)) { + up_write(¤t->mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return 1; + } + + 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("???????? "); + else + printk("%08x ", c); + } + printk("\n"); +} +#endif + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -311,8 +678,10 @@ asmlinkage void __kprobes do_sparc64_fau 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; } @@ -329,6 +698,29 @@ asmlinkage void __kprobes do_sparc64_fau if (!vma) goto bad_area; +#ifdef CONFIG_PAX_PAGEEXEC + /* PaX: detect ITLB misses on non-exec pages */ + if ((mm->pax_flags & MF_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: + return; +#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 @@ -463,7 +855,8 @@ handle_kernel_fault: out_of_memory: insn = get_fault_insn(regs, insn); up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", current->comm); + printk("VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); if (!(regs->tstate & TSTATE_PRIV)) do_exit(SIGKILL); goto handle_kernel_fault; diff -NurpP --minimal linux-2.6.22.19/arch/sparc64/solaris/fs.c linux-2.6.22.19-g-v/arch/sparc64/solaris/fs.c --- linux-2.6.22.19/arch/sparc64/solaris/fs.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/sparc64/solaris/fs.c 2008-03-04 08:55:59.000000000 +0100 @@ -368,7 +368,7 @@ static int report_statvfs(struct vfsmoun int j = strlen (p); if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; + if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt)) i = 1; if (mnt->mnt_flags & MNT_NOSUID) i |= 2; if (!sysv_valid_dev(inode->i_sb->s_dev)) return -EOVERFLOW; @@ -404,7 +404,7 @@ static int report_statvfs64(struct vfsmo int j = strlen (p); if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; + if (IS_RDONLY(inode) || MNT_IS_RDONLY(mnt)) i = 1; if (mnt->mnt_flags & MNT_NOSUID) i |= 2; if (!sysv_valid_dev(inode->i_sb->s_dev)) return -EOVERFLOW; diff -NurpP --minimal linux-2.6.22.19/arch/um/Kconfig linux-2.6.22.19-g-v/arch/um/Kconfig --- linux-2.6.22.19/arch/um/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/um/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -316,6 +316,8 @@ source "drivers/connector/Kconfig" source "fs/Kconfig" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/um/kernel/trap.c linux-2.6.22.19-g-v/arch/um/kernel/trap.c --- linux-2.6.22.19/arch/um/kernel/trap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/um/kernel/trap.c 2008-03-04 08:55:59.000000000 +0100 @@ -210,7 +210,8 @@ unsigned long segv(struct faultinfo fi, current->thread.arch.faultinfo = fi; force_sig_info(SIGBUS, &si, current); } else if (err == -ENOMEM) { - printk("VM: killing process %s\n", current->comm); + printk("VM: killing process %s(%d:#%u)\n", + current->comm, current->pid, current->xid); do_exit(SIGKILL); } else { BUG_ON(err != -EFAULT); diff -NurpP --minimal linux-2.6.22.19/arch/v850/Kconfig linux-2.6.22.19-g-v/arch/v850/Kconfig --- linux-2.6.22.19/arch/v850/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/v850/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -333,6 +333,8 @@ source "drivers/usb/Kconfig" source "arch/v850/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/v850/kernel/module.c linux-2.6.22.19-g-v/arch/v850/kernel/module.c --- linux-2.6.22.19/arch/v850/kernel/module.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/v850/kernel/module.c 2008-03-04 08:55:59.000000000 +0100 @@ -150,8 +150,8 @@ static uint32_t do_plt_call (void *locat tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */ /* Init, or core PLT? */ - if (location >= mod->module_core - && location < mod->module_core + mod->core_size) + if (location >= mod->module_core_rx + && location < mod->module_core_rx + mod->core_size_rx) entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; else entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; diff -NurpP --minimal linux-2.6.22.19/arch/v850/kernel/process.c linux-2.6.22.19-g-v/arch/v850/kernel/process.c --- linux-2.6.22.19/arch/v850/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/v850/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -82,7 +82,7 @@ int kernel_thread (int (*fn)(void *), vo /* Clone this thread. Note that we don't pass the clone syscall's second argument -- it's ignored for calls from kernel mode (the child's SP is always set to the top of the kernel stack). */ - arg0 = flags | CLONE_VM; + arg0 = flags | CLONE_VM | CLONE_KTHREAD; syscall = __NR_clone; asm volatile ("trap " SYSCALL_SHORT_TRAP : "=r" (ret), "=r" (syscall) diff -NurpP --minimal linux-2.6.22.19/arch/v850/kernel/ptrace.c linux-2.6.22.19-g-v/arch/v850/kernel/ptrace.c --- linux-2.6.22.19/arch/v850/kernel/ptrace.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/v850/kernel/ptrace.c 2008-03-04 08:55:59.000000000 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -116,6 +117,9 @@ long arch_ptrace(struct task_struct *chi { int rval; + if (!vx_check(vx_task_xid(child), VS_WATCH_P | VS_IDENT)) + goto out; + switch (request) { unsigned long val, copied; diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/Kconfig linux-2.6.22.19-g-v/arch/x86_64/Kconfig --- linux-2.6.22.19/arch/x86_64/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -782,6 +782,8 @@ endmenu source "arch/x86_64/Kconfig.debug" +source "kernel/vserver/Kconfig" + source "security/Kconfig" source "crypto/Kconfig" diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/ia32_aout.c linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32_aout.c --- linux-2.6.22.19/arch/x86_64/ia32/ia32_aout.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32_aout.c 2008-03-04 08:55:59.000000000 +0100 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32_binfmt.c --- linux-2.6.22.19/arch/x86_64/ia32/ia32_binfmt.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32_binfmt.c 2008-03-04 08:55:59.000000000 +0100 @@ -143,6 +143,13 @@ struct elf_prpsinfo //#include #include +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x08048000UL + +#define PAX_DELTA_MMAP_LEN 16 +#define PAX_DELTA_STACK_LEN 16 +#endif + typedef struct user_i387_ia32_struct elf_fpregset_t; typedef struct user32_fxsr_struct elf_fpxregset_t; @@ -317,27 +324,43 @@ int ia32_setup_arg_pages(struct linux_bi mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; else mpnt->vm_flags = VM_STACK_FLAGS; - mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? - PAGE_COPY_EXEC : PAGE_COPY; + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + mpnt->vm_flags &= ~VM_EXEC; + +#ifdef CONFIG_PAX_MPROTECT + if (mm->pax_flags & MF_PAX_MPROTECT) + mpnt->vm_flags &= ~VM_MAYEXEC; +#endif + + } +#endif + + mpnt->vm_page_prot = vm_get_page_prot(mpnt->vm_flags); if ((ret = insert_vm_struct(mm, mpnt))) { up_write(&mm->mmap_sem); kmem_cache_free(vm_area_cachep, mpnt); return ret; } - mm->stack_vm = mm->total_vm = vma_pages(mpnt); + vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt)); + mm->stack_vm = mm->total_vm; } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { struct page *page = bprm->page[i]; + int retval; if (page) { bprm->page[i] = NULL; - install_arg_page(mpnt, page, stack_base); + retval = install_arg_page(mpnt, page, stack_base); + if (!ret) + ret = retval; } stack_base += PAGE_SIZE; } up_write(&mm->mmap_sem); - - return 0; + + return ret; } EXPORT_SYMBOL(ia32_setup_arg_pages); diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/ia32entry.S linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32entry.S --- linux-2.6.22.19/arch/x86_64/ia32/ia32entry.S 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/ia32entry.S 2008-03-04 08:55:59.000000000 +0100 @@ -680,7 +680,7 @@ ia32_sys_call_table: .quad sys_tgkill /* 270 */ .quad compat_sys_utimes .quad sys32_fadvise64_64 - .quad quiet_ni_syscall /* sys_vserver */ + .quad sys32_vserver .quad sys_mbind .quad compat_sys_get_mempolicy /* 275 */ .quad sys_set_mempolicy diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/mmap32.c linux-2.6.22.19-g-v/arch/x86_64/ia32/mmap32.c --- linux-2.6.22.19/arch/x86_64/ia32/mmap32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/mmap32.c 2008-03-04 08:55:59.000000000 +0100 @@ -69,10 +69,22 @@ void ia32_pick_mmap_layout(struct mm_str (current->personality & ADDR_COMPAT_LAYOUT) || current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { mm->mmap_base = TASK_UNMAPPED_BASE; + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(mm); + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base -= mm->delta_mmap + mm->delta_stack; +#endif + mm->get_unmapped_area = arch_get_unmapped_area_topdown; mm->unmap_area = arch_unmap_area_topdown; } diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/sys_ia32.c linux-2.6.22.19-g-v/arch/x86_64/ia32/sys_ia32.c --- linux-2.6.22.19/arch/x86_64/ia32/sys_ia32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/sys_ia32.c 2008-03-04 08:55:59.000000000 +0100 @@ -454,7 +454,7 @@ sys32_gettimeofday(struct compat_timeval { if (tv) { struct timeval ktv; - do_gettimeofday(&ktv); + vx_gettimeofday(&ktv); if (put_tv32(tv, &ktv)) return -EFAULT; } diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/ia32/syscall32.c linux-2.6.22.19-g-v/arch/x86_64/ia32/syscall32.c --- linux-2.6.22.19/arch/x86_64/ia32/syscall32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/ia32/syscall32.c 2008-03-04 08:55:59.000000000 +0100 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/hpet.c linux-2.6.22.19-g-v/arch/x86_64/kernel/hpet.c --- linux-2.6.22.19/arch/x86_64/kernel/hpet.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/hpet.c 2008-03-04 08:55:59.000000000 +0100 @@ -65,7 +65,7 @@ static __init int late_hpet_init(void) hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE); timer = &hpet->hpet_timers[2]; for (i = 2; i < ntimer; timer++, i++) - hd.hd_irq[i] = (timer->hpet_config & + hd.hd_irq[i] = (readl(&timer->hpet_config) & Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT; diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/ioport.c linux-2.6.22.19-g-v/arch/x86_64/kernel/ioport.c --- linux-2.6.22.19/arch/x86_64/kernel/ioport.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/ioport.c 2008-03-04 08:55:59.000000000 +0100 @@ -41,8 +41,16 @@ asmlinkage long sys_ioperm(unsigned long if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) return -EINVAL; + +#ifdef CONFIG_GRKERNSEC_IO + if (turn_on) { + gr_handle_ioperm(); + return -EPERM; + } +#else if (turn_on && !capable(CAP_SYS_RAWIO)) return -EPERM; +#endif /* * If it's the first ioperm() call in this thread's lifetime, set the @@ -111,8 +119,13 @@ asmlinkage long sys_iopl(unsigned int le 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 &~ X86_EFLAGS_IOPL) | (level << 12); return 0; diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/process.c linux-2.6.22.19-g-v/arch/x86_64/kernel/process.c --- linux-2.6.22.19/arch/x86_64/kernel/process.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/process.c 2008-03-04 08:55:59.000000000 +0100 @@ -54,7 +54,8 @@ asmlinkage extern void ret_from_fork(void); -unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; +unsigned long kernel_thread_flags = + CLONE_VM | CLONE_UNTRACED | CLONE_KTHREAD; unsigned long boot_option_idle_override = 0; EXPORT_SYMBOL(boot_option_idle_override); @@ -310,8 +311,8 @@ void __show_regs(struct pt_regs * regs) printk("\n"); print_modules(); - printk("Pid: %d, comm: %.20s %s %s %.*s\n", - current->pid, current->comm, print_tainted(), + printk("Pid: %d:#%u, comm: %.20s %s %s %.*s\n", + current->pid, current->xid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); @@ -883,10 +884,3 @@ int dump_task_regs(struct task_struct *t return 1; } - -unsigned long arch_align_stack(unsigned long sp) -{ - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() % 8192; - return sp & ~0xf; -} diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/setup64.c linux-2.6.22.19-g-v/arch/x86_64/kernel/setup64.c --- linux-2.6.22.19/arch/x86_64/kernel/setup64.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/setup64.c 2008-03-04 08:55:59.000000000 +0100 @@ -37,7 +37,7 @@ struct desc_ptr idt_descr = { 256 * 16 - char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned"))); unsigned long __supported_pte_mask __read_mostly = ~0UL; -static int do_not_nx __cpuinitdata = 0; +EXPORT_SYMBOL(__supported_pte_mask); /* noexec=on|off Control non executable mappings for 64bit processes. @@ -51,16 +51,14 @@ static int __init nonx_setup(char *str) return -EINVAL; if (!strncmp(str, "on", 2)) { __supported_pte_mask |= _PAGE_NX; - do_not_nx = 0; } else if (!strncmp(str, "off", 3)) { - do_not_nx = 1; __supported_pte_mask &= ~_PAGE_NX; } return 0; } early_param("noexec", nonx_setup); -int force_personality32 = 0; +int force_personality32; /* noexec32=on|off Control non executable heap for 32bit processes. @@ -177,7 +175,7 @@ void __cpuinit check_efer(void) unsigned long efer; rdmsrl(MSR_EFER, efer); - if (!(efer & EFER_NX) || do_not_nx) { + if (!(efer & EFER_NX)) { __supported_pte_mask &= ~_PAGE_NX; } } diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/signal.c linux-2.6.22.19-g-v/arch/x86_64/kernel/signal.c --- linux-2.6.22.19/arch/x86_64/kernel/signal.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/signal.c 2008-03-04 08:55:59.000000000 +0100 @@ -253,8 +253,8 @@ static int setup_rt_frame(int sig, struc err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); if (sizeof(*set) == 16) { - __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); - __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); + err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); + err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); } else err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/sys_x86_64.c linux-2.6.22.19-g-v/arch/x86_64/kernel/sys_x86_64.c --- linux-2.6.22.19/arch/x86_64/kernel/sys_x86_64.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/sys_x86_64.c 2008-03-04 08:55:59.000000000 +0100 @@ -64,8 +64,8 @@ out: return error; } -static void find_start_end(unsigned long flags, unsigned long *begin, - unsigned long *end) +static void find_start_end(struct mm_struct *mm, unsigned long flags, + unsigned long *begin, unsigned long *end) { if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) { /* This is usually used needed to map code in small @@ -78,7 +78,7 @@ static void find_start_end(unsigned long *begin = 0x40000000; *end = 0x80000000; } else { - *begin = TASK_UNMAPPED_BASE; + *begin = mm->mmap_base; *end = TASK_SIZE; } } @@ -95,11 +95,15 @@ arch_get_unmapped_area(struct file *filp if (flags & MAP_FIXED) return addr; - find_start_end(flags, &begin, &end); + find_start_end(mm, flags, &begin, &end); if (len > end) return -ENOMEM; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp) +#endif + if (addr) { addr = PAGE_ALIGN(addr); vma = find_vma(mm, addr); diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/kernel/traps.c linux-2.6.22.19-g-v/arch/x86_64/kernel/traps.c --- linux-2.6.22.19/arch/x86_64/kernel/traps.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/kernel/traps.c 2008-03-04 08:55:59.000000000 +0100 @@ -413,8 +413,9 @@ void show_registers(struct pt_regs *regs rsp = regs->rsp; printk("CPU %d ", cpu); __show_regs(regs); - printk("Process %s (pid: %d, threadinfo %p, task %p)\n", - cur->comm, cur->pid, task_thread_info(cur), cur); + printk("Process %s (pid: %d[#%u], threadinfo %p, task %p)\n", + cur->comm, cur->pid, cur->xid, + task_thread_info(cur), cur); /* * When in-kernel, we also print out the stack and code at the @@ -580,8 +581,8 @@ static void __kprobes do_trap(int trapnr if (exception_trace && unhandled_signal(tsk, signr)) printk(KERN_INFO - "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", - tsk->comm, tsk->pid, str, + "%s[%d:#%u] trap %s rip:%lx rsp:%lx error:%lx\n", + tsk->comm, tsk->pid, tsk->xid, str, regs->rip, regs->rsp, error_code); if (info) @@ -684,8 +685,8 @@ asmlinkage void __kprobes do_general_pro if (exception_trace && unhandled_signal(tsk, SIGSEGV)) printk(KERN_INFO - "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", - tsk->comm, tsk->pid, + "%s[%d:#%u] general protection rip:%lx rsp:%lx error:%lx\n", + tsk->comm, tsk->pid, tsk->xid, regs->rip, regs->rsp, error_code); force_sig(SIGSEGV, tsk); diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/mm/fault.c linux-2.6.22.19-g-v/arch/x86_64/mm/fault.c --- linux-2.6.22.19/arch/x86_64/mm/fault.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/mm/fault.c 2008-03-04 08:55:59.000000000 +0100 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -301,6 +302,33 @@ static int vmalloc_fault(unsigned long a return 0; } +#ifdef CONFIG_PAX_PAGEEXEC +void pax_report_insns(void *pc, void *sp) +{ + long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 20; i++) { + unsigned char c; + if (get_user(c, (unsigned char __user *)pc+i)) + printk("?? "); + else + printk("%02x ", c); + } + printk("\n"); + + printk(KERN_ERR "PAX: bytes at SP-8: "); + for (i = -1; i < 10; i++) { + unsigned long c; + if (get_user(c, (unsigned long __user *)sp+i)) + printk("???????????????? "); + else + printk("%016lx ", c); + } + printk("\n"); +} +#endif + int page_fault_trace = 0; int exception_trace = 1; @@ -430,6 +458,8 @@ asmlinkage void __kprobes do_page_fault( good_area: info.si_code = SEGV_ACCERR; write = 0; + if ((error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC)) + goto bad_area; switch (error_code & (PF_PROT|PF_WRITE)) { default: /* 3: write, present */ /* fall through */ @@ -497,12 +527,19 @@ bad_area_nosemaphore: if (exception_trace && unhandled_signal(tsk, SIGSEGV)) { printk( - "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", + "%s%s[%d:#%u]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", tsk->pid > 1 ? KERN_INFO : KERN_EMERG, - tsk->comm, tsk->pid, address, regs->rip, - regs->rsp, error_code); + tsk->comm, tsk->pid, tsk->xid, address, + regs->rip, regs->rsp, error_code); } - + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm && (mm->pax_flags & MF_PAX_PAGEEXEC) && (error_code & 16)) { + pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp); + do_exit(SIGKILL); + } +#endif + tsk->thread.cr2 = address; /* Kernel addresses are always protection faults */ tsk->thread.error_code = error_code | (address >= TASK_SIZE); @@ -567,7 +604,8 @@ out_of_memory: yield(); goto again; } - printk("VM: killing process %s\n", tsk->comm); + printk("VM: killing process %s(%d:#%u)\n", + tsk->comm, tsk->pid, tsk->xid); if (error_code & 4) do_exit(SIGKILL); goto no_context; diff -NurpP --minimal linux-2.6.22.19/arch/x86_64/mm/mmap.c linux-2.6.22.19-g-v/arch/x86_64/mm/mmap.c --- linux-2.6.22.19/arch/x86_64/mm/mmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/arch/x86_64/mm/mmap.c 2008-03-04 08:55:59.000000000 +0100 @@ -23,6 +23,12 @@ void arch_pick_mmap_layout(struct mm_str unsigned rnd = get_random_int() & 0xfffffff; mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; } + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + mm->mmap_base += mm->delta_mmap; +#endif + mm->get_unmapped_area = arch_get_unmapped_area; mm->unmap_area = arch_unmap_area; } diff -NurpP --minimal linux-2.6.22.19/crypto/lrw.c linux-2.6.22.19-g-v/crypto/lrw.c --- linux-2.6.22.19/crypto/lrw.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/crypto/lrw.c 2008-03-04 08:55:59.000000000 +0100 @@ -54,7 +54,7 @@ static int setkey(struct crypto_tfm *par struct priv *ctx = crypto_tfm_ctx(parent); struct crypto_cipher *child = ctx->child; int err, i; - be128 tmp = { 0 }; + be128 tmp = { 0, 0 }; int bsize = crypto_cipher_blocksize(child); crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/blacklist.c linux-2.6.22.19-g-v/drivers/acpi/blacklist.c --- linux-2.6.22.19/drivers/acpi/blacklist.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/blacklist.c 2008-03-04 08:55:59.000000000 +0100 @@ -70,7 +70,7 @@ static struct acpi_blacklist_item acpi_b {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions, "Bogus PCI routing", 1}, - {""} + {"", "", 0, 0, 0, all_versions, 0} }; #if CONFIG_ACPI_BLACKLIST_YEAR diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/glue.c linux-2.6.22.19-g-v/drivers/acpi/glue.c --- linux-2.6.22.19/drivers/acpi/glue.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/glue.c 2008-03-04 08:55:59.000000000 +0100 @@ -16,7 +16,7 @@ #if ACPI_GLUE_DEBUG #define DBG(x...) printk(PREFIX x) #else -#define DBG(x...) +#define DBG(x...) do {} while (0) #endif static LIST_HEAD(bus_type_list); static DECLARE_RWSEM(bus_type_sem); diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/processor_core.c linux-2.6.22.19-g-v/drivers/acpi/processor_core.c --- linux-2.6.22.19/drivers/acpi/processor_core.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/processor_core.c 2008-03-04 08:55:59.000000000 +0100 @@ -637,7 +637,7 @@ static int __cpuinit acpi_processor_star return 0; } - BUG_ON((pr->id >= NR_CPUS) || (pr->id < 0)); + BUG_ON(pr->id >= NR_CPUS); /* * Buggy BIOS check diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/processor_idle.c linux-2.6.22.19-g-v/drivers/acpi/processor_idle.c --- linux-2.6.22.19/drivers/acpi/processor_idle.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/processor_idle.c 2008-03-04 08:55:59.000000000 +0100 @@ -163,7 +163,7 @@ static struct dmi_system_id __cpuinitdat DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, (void *)2}, - {}, + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL}, }; static inline u32 ticks_elapsed(u32 t1, u32 t2) diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/sleep/main.c linux-2.6.22.19-g-v/drivers/acpi/sleep/main.c --- linux-2.6.22.19/drivers/acpi/sleep/main.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/sleep/main.c 2008-03-04 08:55:59.000000000 +0100 @@ -241,7 +241,7 @@ static struct dmi_system_id __initdata a .ident = "Toshiba Satellite 4030cdt", .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, }, - {}, + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL}, }; int __init acpi_sleep_init(void) diff -NurpP --minimal linux-2.6.22.19/drivers/acpi/tables/tbfadt.c linux-2.6.22.19-g-v/drivers/acpi/tables/tbfadt.c --- linux-2.6.22.19/drivers/acpi/tables/tbfadt.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/acpi/tables/tbfadt.c 2008-03-04 08:55:59.000000000 +0100 @@ -48,7 +48,7 @@ ACPI_MODULE_NAME("tbfadt") /* Local prototypes */ -static void inline +static inline void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, u8 bit_width, u64 address); @@ -122,7 +122,7 @@ static struct acpi_fadt_info fadt_info_t * ******************************************************************************/ -static void inline +static inline void acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, u8 bit_width, u64 address) { diff -NurpP --minimal linux-2.6.22.19/drivers/ata/ata_piix.c linux-2.6.22.19-g-v/drivers/ata/ata_piix.c --- linux-2.6.22.19/drivers/ata/ata_piix.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ata/ata_piix.c 2008-03-04 08:55:59.000000000 +0100 @@ -246,7 +246,7 @@ static const struct pci_device_id piix_p /* SATA Controller IDE (ICH9M) */ { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - { } /* terminate list */ + { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ }; static struct pci_driver piix_pci_driver = { @@ -582,7 +582,7 @@ static const struct ich_laptop ich_lapto { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ /* end marker */ - { 0, } + { 0, 0, 0 } }; /** diff -NurpP --minimal linux-2.6.22.19/drivers/ata/libata-core.c linux-2.6.22.19-g-v/drivers/ata/libata-core.c --- linux-2.6.22.19/drivers/ata/libata-core.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ata/libata-core.c 2008-03-04 08:55:59.000000000 +0100 @@ -469,7 +469,7 @@ static const struct ata_xfer_ent { { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 }, { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 }, - { -1, }, + { -1, 0, 0 }, }; /** @@ -2559,7 +2559,7 @@ static const struct ata_timing ata_timin /* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */ - { 0xFF } + { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0 } }; #define ENOUGH(v,unit) (((v)-1)/(unit)+1) @@ -3806,7 +3806,7 @@ static const struct ata_blacklist_entry { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, /* End Marker */ - { } + { NULL, NULL, 0 } }; unsigned long ata_device_blacklisted(const struct ata_device *dev) diff -NurpP --minimal linux-2.6.22.19/drivers/block/Kconfig linux-2.6.22.19-g-v/drivers/block/Kconfig --- linux-2.6.22.19/drivers/block/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/block/Kconfig 2008-03-04 08:55:59.000000000 +0100 @@ -311,6 +311,13 @@ config BLK_DEV_CRYPTOLOOP instead, which can be configured to be on-disk compatible with the cryptoloop device. +config BLK_DEV_VROOT + tristate "Virtual Root device support" + depends on QUOTACTL + ---help--- + Saying Y here will allow you to use quota/fs ioctls on a shared + partition within a virtual server without compromising security. + config BLK_DEV_NBD tristate "Network block device support" depends on NET diff -NurpP --minimal linux-2.6.22.19/drivers/block/Makefile linux-2.6.22.19-g-v/drivers/block/Makefile --- linux-2.6.22.19/drivers/block/Makefile 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/block/Makefile 2008-03-04 08:55:59.000000000 +0100 @@ -28,4 +28,5 @@ obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryp obj-$(CONFIG_VIODASD) += viodasd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o +obj-$(CONFIG_BLK_DEV_VROOT) += vroot.o diff -NurpP --minimal linux-2.6.22.19/drivers/block/loop.c linux-2.6.22.19-g-v/drivers/block/loop.c --- linux-2.6.22.19/drivers/block/loop.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/block/loop.c 2008-03-04 08:55:59.000000000 +0100 @@ -74,6 +74,7 @@ #include #include #include +#include #include @@ -790,6 +791,7 @@ static int loop_set_fd(struct loop_devic lo->lo_blocksize = lo_blocksize; lo->lo_device = bdev; lo->lo_flags = lo_flags; + lo->lo_xid = vx_current_xid(); lo->lo_backing_file = file; lo->transfer = transfer_none; lo->ioctl = NULL; @@ -909,6 +911,7 @@ static int loop_clr_fd(struct loop_devic lo->lo_encrypt_key_size = 0; lo->lo_flags = 0; lo->lo_thread = NULL; + lo->lo_xid = 0; memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); @@ -930,7 +933,7 @@ loop_set_status(struct loop_device *lo, struct loop_func_table *xfer; if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && - !capable(CAP_SYS_ADMIN)) + !vx_capable(CAP_SYS_ADMIN, VXC_ADMIN_CLOOP)) return -EPERM; if (lo->lo_state != Lo_bound) return -ENXIO; @@ -1010,7 +1013,8 @@ loop_get_status(struct loop_device *lo, memcpy(info->lo_crypt_name, lo->lo_crypt_name, LO_NAME_SIZE); info->lo_encrypt_type = lo->lo_encryption ? lo->lo_encryption->number : 0; - if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) { + if (lo->lo_encrypt_key_size && + vx_capable(CAP_SYS_ADMIN, VXC_ADMIN_CLOOP)) { info->lo_encrypt_key_size = lo->lo_encrypt_key_size; memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, lo->lo_encrypt_key_size); @@ -1321,6 +1325,9 @@ static int lo_open(struct inode *inode, { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; + if (!vx_check(lo->lo_xid, VS_IDENT|VS_HOSTID)) + return -EACCES; + mutex_lock(&lo->lo_ctl_mutex); lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); diff -NurpP --minimal linux-2.6.22.19/drivers/block/vroot.c linux-2.6.22.19-g-v/drivers/block/vroot.c --- linux-2.6.22.19/drivers/block/vroot.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/block/vroot.c 2008-03-04 08:55:59.000000000 +0100 @@ -0,0 +1,281 @@ +/* + * linux/drivers/block/vroot.c + * + * written by Herbert Pötzl, 9/11/2002 + * ported to 2.6.10 by Herbert Pötzl, 30/12/2004 + * + * based on the loop.c code by Theodore Ts'o. + * + * Copyright (C) 2002-2007 by Herbert Pötzl. + * Redistribution of this file is permitted under the + * GNU General Public License. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + + +static int max_vroot = 8; + +static struct vroot_device *vroot_dev; +static struct gendisk **disks; + + +static int vroot_set_dev( + struct vroot_device *vr, + struct file *vr_file, + struct block_device *bdev, + unsigned int arg) +{ + struct block_device *real_bdev; + struct file *file; + struct inode *inode; + int error; + + error = -EBUSY; + if (vr->vr_state != Vr_unbound) + goto out; + + error = -EBADF; + file = fget(arg); + if (!file) + goto out; + + error = -EINVAL; + inode = file->f_dentry->d_inode; + + + if (S_ISBLK(inode->i_mode)) { + real_bdev = inode->i_bdev; + vr->vr_device = real_bdev; + __iget(real_bdev->bd_inode); + } else + goto out_fput; + + vxdprintk(VXD_CBIT(misc, 0), + "vroot[%d]_set_dev: dev=" VXF_DEV, + vr->vr_number, VXD_DEV(real_bdev)); + + vr->vr_state = Vr_bound; + error = 0; + + out_fput: + fput(file); + out: + return error; +} + +static int vroot_clr_dev( + struct vroot_device *vr, + struct file *vr_file, + struct block_device *bdev) +{ + struct block_device *real_bdev; + + if (vr->vr_state != Vr_bound) + return -ENXIO; + if (vr->vr_refcnt > 1) /* we needed one fd for the ioctl */ + return -EBUSY; + + real_bdev = vr->vr_device; + + vxdprintk(VXD_CBIT(misc, 0), + "vroot[%d]_clr_dev: dev=" VXF_DEV, + vr->vr_number, VXD_DEV(real_bdev)); + + bdput(real_bdev); + vr->vr_state = Vr_unbound; + vr->vr_device = NULL; + return 0; +} + + +static int vr_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct vroot_device *vr = inode->i_bdev->bd_disk->private_data; + int err; + + down(&vr->vr_ctl_mutex); + switch (cmd) { + case VROOT_SET_DEV: + err = vroot_set_dev(vr, file, inode->i_bdev, arg); + break; + case VROOT_CLR_DEV: + err = vroot_clr_dev(vr, file, inode->i_bdev); + break; + default: + err = -EINVAL; + break; + } + up(&vr->vr_ctl_mutex); + return err; +} + +static int vr_open(struct inode *inode, struct file *file) +{ + struct vroot_device *vr = inode->i_bdev->bd_disk->private_data; + + down(&vr->vr_ctl_mutex); + vr->vr_refcnt++; + up(&vr->vr_ctl_mutex); + return 0; +} + +static int vr_release(struct inode *inode, struct file *file) +{ + struct vroot_device *vr = inode->i_bdev->bd_disk->private_data; + + down(&vr->vr_ctl_mutex); + --vr->vr_refcnt; + up(&vr->vr_ctl_mutex); + return 0; +} + +static struct block_device_operations vr_fops = { + .owner = THIS_MODULE, + .open = vr_open, + .release = vr_release, + .ioctl = vr_ioctl, +}; + +struct block_device *__vroot_get_real_bdev(struct block_device *bdev) +{ + struct inode *inode = bdev->bd_inode; + struct vroot_device *vr; + struct block_device *real_bdev; + int minor = iminor(inode); + + vr = &vroot_dev[minor]; + real_bdev = vr->vr_device; + + vxdprintk(VXD_CBIT(misc, 0), + "vroot[%d]_get_real_bdev: dev=" VXF_DEV, + vr->vr_number, VXD_DEV(real_bdev)); + + if (vr->vr_state != Vr_bound) + return ERR_PTR(-ENXIO); + + __iget(real_bdev->bd_inode); + return real_bdev; +} + +/* + * And now the modules code and kernel interface. + */ + +module_param(max_vroot, int, 0); + +MODULE_PARM_DESC(max_vroot, "Maximum number of vroot devices (1-256)"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_BLOCKDEV_MAJOR(VROOT_MAJOR); + +MODULE_AUTHOR ("Herbert Pötzl"); +MODULE_DESCRIPTION ("Virtual Root Device Mapper"); + + +int __init vroot_init(void) +{ + int err, i; + + if (max_vroot < 1 || max_vroot > 256) { + max_vroot = MAX_VROOT_DEFAULT; + printk(KERN_WARNING "vroot: invalid max_vroot " + "(must be between 1 and 256), " + "using default (%d)\n", max_vroot); + } + + if (register_blkdev(VROOT_MAJOR, "vroot")) + return -EIO; + + err = -ENOMEM; + vroot_dev = kmalloc(max_vroot * sizeof(struct vroot_device), GFP_KERNEL); + if (!vroot_dev) + goto out_mem1; + memset(vroot_dev, 0, max_vroot * sizeof(struct vroot_device)); + + disks = kmalloc(max_vroot * sizeof(struct gendisk *), GFP_KERNEL); + if (!disks) + goto out_mem2; + + for (i = 0; i < max_vroot; i++) { + disks[i] = alloc_disk(1); + if (!disks[i]) + goto out_mem3; + } + + for (i = 0; i < max_vroot; i++) { + struct vroot_device *vr = &vroot_dev[i]; + struct gendisk *disk = disks[i]; + + memset(vr, 0, sizeof(*vr)); + init_MUTEX(&vr->vr_ctl_mutex); + vr->vr_number = i; + disk->major = VROOT_MAJOR; + disk->first_minor = i; + disk->fops = &vr_fops; + sprintf(disk->disk_name, "vroot%d", i); + disk->private_data = vr; + } + + err = register_vroot_grb(&__vroot_get_real_bdev); + if (err) + goto out_mem3; + + for (i = 0; i < max_vroot; i++) + add_disk(disks[i]); + printk(KERN_INFO "vroot: loaded (max %d devices)\n", max_vroot); + return 0; + +out_mem3: + while (i--) + put_disk(disks[i]); + kfree(disks); +out_mem2: + kfree(vroot_dev); +out_mem1: + unregister_blkdev(VROOT_MAJOR, "vroot"); + printk(KERN_ERR "vroot: ran out of memory\n"); + return err; +} + +void vroot_exit(void) +{ + int i; + + if (unregister_vroot_grb(&__vroot_get_real_bdev)) + printk(KERN_WARNING "vroot: cannot unregister grb\n"); + + for (i = 0; i < max_vroot; i++) { + del_gendisk(disks[i]); + put_disk(disks[i]); + } + if (unregister_blkdev(VROOT_MAJOR, "vroot")) + printk(KERN_WARNING "vroot: cannot unregister blkdev\n"); + + kfree(disks); + kfree(vroot_dev); +} + +module_init(vroot_init); +module_exit(vroot_exit); + +#ifndef MODULE + +static int __init max_vroot_setup(char *str) +{ + max_vroot = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("max_vroot=", max_vroot_setup); + +#endif + diff -NurpP --minimal linux-2.6.22.19/drivers/char/agp/frontend.c linux-2.6.22.19-g-v/drivers/char/agp/frontend.c --- linux-2.6.22.19/drivers/char/agp/frontend.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/agp/frontend.c 2008-03-04 08:55:59.000000000 +0100 @@ -819,7 +819,7 @@ static int agpioc_reserve_wrap(struct ag if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) return -EFAULT; - if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) + if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv)) return -EFAULT; client = agp_find_client_by_pid(reserve.pid); diff -NurpP --minimal linux-2.6.22.19/drivers/char/agp/intel-agp.c linux-2.6.22.19-g-v/drivers/char/agp/intel-agp.c --- linux-2.6.22.19/drivers/char/agp/intel-agp.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/agp/intel-agp.c 2008-03-04 08:55:59.000000000 +0100 @@ -2066,7 +2066,7 @@ static struct pci_device_id agp_intel_pc ID(PCI_DEVICE_ID_INTEL_G33_HB), ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB), - { } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); diff -NurpP --minimal linux-2.6.22.19/drivers/char/drm/drm_drawable.c linux-2.6.22.19-g-v/drivers/char/drm/drm_drawable.c --- linux-2.6.22.19/drivers/char/drm/drm_drawable.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/drm/drm_drawable.c 2008-03-04 08:55:59.000000000 +0100 @@ -245,7 +245,7 @@ int drm_update_drawable_info(DRM_IOCTL_A idx = id / (8 * sizeof(*bitfield)); shift = id % (8 * sizeof(*bitfield)); - if (idx < 0 || idx >= bitfield_length || + if (idx >= bitfield_length || !(bitfield[idx] & (1 << shift))) { DRM_ERROR("No such drawable %d\n", update.handle); return DRM_ERR(EINVAL); @@ -330,7 +330,7 @@ drm_drawable_info_t *drm_get_drawable_in idx = id / (8 * sizeof(*bitfield)); shift = id % (8 * sizeof(*bitfield)); - if (idx < 0 || idx >= dev->drw_bitfield_length || + if (idx >= dev->drw_bitfield_length || !(bitfield[idx] & (1 << shift))) { DRM_DEBUG("No such drawable %d\n", id); return NULL; diff -NurpP --minimal linux-2.6.22.19/drivers/char/drm/drm_pciids.h linux-2.6.22.19-g-v/drivers/char/drm/drm_pciids.h --- linux-2.6.22.19/drivers/char/drm/drm_pciids.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/drm/drm_pciids.h 2008-03-04 08:55:59.000000000 +0100 @@ -251,7 +251,7 @@ {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ - {0, 0, 0} + {0, 0, 0, 0, 0, 0, 0 } #define i830_PCI_IDS \ {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ diff -NurpP --minimal linux-2.6.22.19/drivers/char/hpet.c linux-2.6.22.19-g-v/drivers/char/hpet.c --- linux-2.6.22.19/drivers/char/hpet.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/hpet.c 2008-03-04 08:55:59.000000000 +0100 @@ -1008,7 +1008,7 @@ static struct acpi_driver hpet_acpi_driv }, }; -static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; +static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops, {NULL, NULL}, NULL, NULL }; static int __init hpet_init(void) { diff -NurpP --minimal linux-2.6.22.19/drivers/char/keyboard.c linux-2.6.22.19-g-v/drivers/char/keyboard.c --- linux-2.6.22.19/drivers/char/keyboard.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/keyboard.c 2008-03-04 08:55:59.000000000 +0100 @@ -595,6 +595,16 @@ static void k_spec(struct vc_data *vc, u 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); } @@ -1334,7 +1344,7 @@ static const struct input_device_id kbd_ .evbit = { BIT(EV_SND) }, }, - { }, /* Terminating entry */ + { 0 }, /* Terminating entry */ }; MODULE_DEVICE_TABLE(input, kbd_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/char/mem.c linux-2.6.22.19-g-v/drivers/char/mem.c --- linux-2.6.22.19/drivers/char/mem.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/mem.c 2008-03-04 08:55:59.000000000 +0100 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,10 @@ # include #endif +#ifdef CONFIG_GRKERNSEC +extern struct file_operations grsec_fops; +#endif + /* * Architectures vary in how they handle caching for addresses * outside of main memory. @@ -173,6 +178,11 @@ static ssize_t write_mem(struct file * f if (!valid_phys_addr_range(p, count)) return -EFAULT; +#ifdef CONFIG_GRKERNSEC_KMEM + gr_handle_mem_write(); + return -EPERM; +#endif + written = 0; #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED @@ -274,6 +284,11 @@ static int mmap_mem(struct file * file, if (!private_mapping_ok(vma)) return -ENOSYS; +#ifdef CONFIG_GRKERNSEC_KMEM + if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma)) + return -EPERM; +#endif + vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, size, vma->vm_page_prot); @@ -505,6 +520,11 @@ static ssize_t write_kmem(struct file * 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; @@ -628,6 +648,10 @@ static inline size_t read_zero_pagealign struct vm_area_struct * vma; unsigned long addr=(unsigned long)buf; +#ifdef CONFIG_PAX_SEGMEXEC + struct vm_area_struct *vma_m; +#endif + mm = current->mm; /* Oops, this was forgotten before. -ben */ down_read(&mm->mmap_sem); @@ -644,8 +668,14 @@ static inline size_t read_zero_pagealign if (count > size) count = size; +#ifdef CONFIG_PAX_SEGMEXEC + vma_m = pax_find_mirror_vma(vma); + if (vma_m) + zap_page_range(vma_m, addr + SEGMEXEC_TASK_SIZE, count, NULL); +#endif + zap_page_range(vma, addr, count, NULL); - if (zeromap_page_range(vma, addr, count, PAGE_COPY)) + if (zeromap_page_range(vma, addr, count, vma->vm_page_prot)) break; size -= count; @@ -798,6 +828,16 @@ static loff_t memory_lseek(struct file * 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; } @@ -805,7 +845,6 @@ static int open_port(struct inode * inod #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 #define open_oldmem open_mem @@ -938,6 +977,11 @@ static int memory_open(struct inode * in filp->f_op = &oldmem_fops; break; #endif +#ifdef CONFIG_GRKERNSEC + case 13: + filp->f_op = &grsec_fops; + break; +#endif default: return -ENXIO; } @@ -970,6 +1014,9 @@ static const struct { #ifdef CONFIG_CRASH_DUMP {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops}, #endif +#ifdef CONFIG_GRKERNSEC + {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops}, +#endif }; static struct class *mem_class; diff -NurpP --minimal linux-2.6.22.19/drivers/char/nvram.c linux-2.6.22.19-g-v/drivers/char/nvram.c --- linux-2.6.22.19/drivers/char/nvram.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/nvram.c 2008-03-04 08:55:59.000000000 +0100 @@ -449,7 +449,10 @@ static const struct file_operations nvra static struct miscdevice nvram_dev = { NVRAM_MINOR, "nvram", - &nvram_fops + &nvram_fops, + {NULL, NULL}, + NULL, + NULL }; static int __init diff -NurpP --minimal linux-2.6.22.19/drivers/char/random.c linux-2.6.22.19-g-v/drivers/char/random.c --- linux-2.6.22.19/drivers/char/random.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/random.c 2008-03-04 08:55:59.000000000 +0100 @@ -248,8 +248,13 @@ /* * Configuration information */ +#ifdef CONFIG_GRKERNSEC_RANDNET +#define INPUT_POOL_WORDS 512 +#define OUTPUT_POOL_WORDS 128 +#else #define INPUT_POOL_WORDS 128 #define OUTPUT_POOL_WORDS 32 +#endif #define SEC_XFER_SIZE 512 /* @@ -286,10 +291,17 @@ static struct poolinfo { int poolwords; int tap1, tap2, tap3, tap4, tap5; } poolinfo_table[] = { +#ifdef CONFIG_GRKERNSEC_RANDNET + /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */ + { 512, 411, 308, 208, 104, 1 }, + /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */ + { 128, 103, 76, 51, 25, 1 }, +#else /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */ { 128, 103, 76, 51, 25, 1 }, /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */ { 32, 26, 20, 14, 7, 1 }, +#endif #if 0 /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */ { 2048, 1638, 1231, 819, 411, 1 }, diff -NurpP --minimal linux-2.6.22.19/drivers/char/sysrq.c linux-2.6.22.19-g-v/drivers/char/sysrq.c --- linux-2.6.22.19/drivers/char/sysrq.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/sysrq.c 2008-03-04 08:55:59.000000000 +0100 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -309,6 +310,21 @@ static struct sysrq_key_op sysrq_unrt_op .enable_mask = SYSRQ_ENABLE_RTNICE, }; + +#ifdef CONFIG_VSERVER_DEBUG +static void sysrq_handle_vxinfo(int key, struct tty_struct *tty) +{ + dump_vx_info_inactive((key == 'x')?0:1); +} + +static struct sysrq_key_op sysrq_showvxinfo_op = { + .handler = sysrq_handle_vxinfo, + .help_msg = "conteXt", + .action_msg = "Show Context Info", + .enable_mask = SYSRQ_ENABLE_DUMP, +}; +#endif + /* Key Operations table and lock */ static DEFINE_SPINLOCK(sysrq_key_table_lock); @@ -357,7 +373,11 @@ static struct sysrq_key_op *sysrq_key_ta /* x: May be registered on ppc/powerpc for xmon */ NULL, /* x */ NULL, /* y */ - NULL /* z */ +#ifdef CONFIG_VSERVER_DEBUG + &sysrq_showvxinfo_op, /* z */ +#else + NULL, /* z */ +#endif }; /* key2index calculation, -1 on invalid index */ @@ -369,6 +389,8 @@ static int sysrq_key_table_key2index(int retval = key - '0'; else if ((key >= 'a') && (key <= 'z')) retval = key + 10 - 'a'; + else if ((key >= 'A') && (key <= 'Z')) + retval = key + 10 - 'A'; else retval = -1; return retval; diff -NurpP --minimal linux-2.6.22.19/drivers/char/tty_io.c linux-2.6.22.19-g-v/drivers/char/tty_io.c --- linux-2.6.22.19/drivers/char/tty_io.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/tty_io.c 2008-03-04 08:55:59.000000000 +0100 @@ -103,6 +103,7 @@ #include #include +#include #undef TTY_DEBUG_HANGUP @@ -3049,13 +3050,15 @@ unlock: static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { + pid_t pgrp; /* * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; - return put_user(pid_nr(real_tty->pgrp), p); + pgrp = vx_map_pid(pid_nr(real_tty->pgrp)); + return put_user(pgrp, p); } /** @@ -3086,6 +3089,7 @@ static int tiocspgrp(struct tty_struct * return -ENOTTY; if (get_user(pgrp_nr, p)) return -EFAULT; + pgrp_nr = vx_rmap_pid(pgrp_nr); if (pgrp_nr < 0) return -EINVAL; rcu_read_lock(); diff -NurpP --minimal linux-2.6.22.19/drivers/char/vt_ioctl.c linux-2.6.22.19-g-v/drivers/char/vt_ioctl.c --- linux-2.6.22.19/drivers/char/vt_ioctl.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/char/vt_ioctl.c 2008-03-04 08:55:59.000000000 +0100 @@ -95,6 +95,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __ case KDSKBENT: if (!perm) return -EPERM; + +#ifdef CONFIG_GRKERNSEC + if (!capable(CAP_SYS_TTY_CONFIG)) + return -EPERM; +#endif + if (!i && v == K_NOSUCHMAP) { /* deallocate map */ key_map = key_maps[s]; @@ -235,6 +241,13 @@ do_kdgkb_ioctl(int cmd, struct kbsentry goto reterr; } +#ifdef CONFIG_GRKERNSEC + if (!capable(CAP_SYS_TTY_CONFIG)) { + ret = -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 -NurpP --minimal linux-2.6.22.19/drivers/edac/edac_mc.h linux-2.6.22.19-g-v/drivers/edac/edac_mc.h --- linux-2.6.22.19/drivers/edac/edac_mc.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/edac/edac_mc.h 2008-03-04 08:55:59.000000000 +0100 @@ -71,11 +71,11 @@ extern int edac_debug_level; #else /* !CONFIG_EDAC_DEBUG */ -#define debugf0( ... ) -#define debugf1( ... ) -#define debugf2( ... ) -#define debugf3( ... ) -#define debugf4( ... ) +#define debugf0( ... ) do {} while (0) +#define debugf1( ... ) do {} while (0) +#define debugf2( ... ) do {} while (0) +#define debugf3( ... ) do {} while (0) +#define debugf4( ... ) do {} while (0) #endif /* !CONFIG_EDAC_DEBUG */ diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/fscpos.c linux-2.6.22.19-g-v/drivers/hwmon/fscpos.c --- linux-2.6.22.19/drivers/hwmon/fscpos.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/fscpos.c 2008-03-04 08:55:59.000000000 +0100 @@ -231,7 +231,6 @@ static ssize_t set_pwm(struct i2c_client unsigned long v = simple_strtoul(buf, NULL, 10); /* Range: 0..255 */ - if (v < 0) v = 0; if (v > 255) v = 255; mutex_lock(&data->update_lock); diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/k8temp.c linux-2.6.22.19-g-v/drivers/hwmon/k8temp.c --- linux-2.6.22.19/drivers/hwmon/k8temp.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/k8temp.c 2008-03-04 08:55:59.000000000 +0100 @@ -130,7 +130,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n static struct pci_device_id k8temp_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, - { 0 }, + { 0, 0, 0, 0, 0, 0, 0 }, }; MODULE_DEVICE_TABLE(pci, k8temp_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/sis5595.c linux-2.6.22.19-g-v/drivers/hwmon/sis5595.c --- linux-2.6.22.19/drivers/hwmon/sis5595.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/sis5595.c 2008-03-04 08:55:59.000000000 +0100 @@ -755,7 +755,7 @@ static struct sis5595_data *sis5595_upda static struct pci_device_id sis5595_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, sis5595_pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/via686a.c linux-2.6.22.19-g-v/drivers/hwmon/via686a.c --- linux-2.6.22.19/drivers/hwmon/via686a.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/via686a.c 2008-03-04 08:55:59.000000000 +0100 @@ -813,7 +813,7 @@ static struct via686a_data *via686a_upda static struct pci_device_id via686a_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, via686a_pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/vt8231.c linux-2.6.22.19-g-v/drivers/hwmon/vt8231.c --- linux-2.6.22.19/drivers/hwmon/vt8231.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/vt8231.c 2008-03-04 08:55:59.000000000 +0100 @@ -666,7 +666,7 @@ static struct i2c_driver vt8231_driver = static struct pci_device_id vt8231_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, vt8231_pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/hwmon/w83791d.c linux-2.6.22.19-g-v/drivers/hwmon/w83791d.c --- linux-2.6.22.19/drivers/hwmon/w83791d.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/hwmon/w83791d.c 2008-03-04 08:55:59.000000000 +0100 @@ -289,8 +289,8 @@ static int w83791d_attach_adapter(struct static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); static int w83791d_detach_client(struct i2c_client *client); -static int w83791d_read(struct i2c_client *client, u8 register); -static int w83791d_write(struct i2c_client *client, u8 register, u8 value); +static int w83791d_read(struct i2c_client *client, u8 reg); +static int w83791d_write(struct i2c_client *client, u8 reg, u8 value); static struct w83791d_data *w83791d_update_device(struct device *dev); #ifdef DEBUG diff -NurpP --minimal linux-2.6.22.19/drivers/i2c/busses/i2c-i801.c linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-i801.c --- linux-2.6.22.19/drivers/i2c/busses/i2c-i801.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-i801.c 2008-03-04 08:55:59.000000000 +0100 @@ -460,7 +460,7 @@ static struct pci_device_id i801_ids[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE (pci, i801_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/i2c/busses/i2c-i810.c linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-i810.c --- linux-2.6.22.19/drivers/i2c/busses/i2c-i810.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-i810.c 2008-03-04 08:55:59.000000000 +0100 @@ -198,7 +198,7 @@ static struct pci_device_id i810_ids[] _ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) }, - { 0, }, + { 0, 0, 0, 0, 0, 0, 0 }, }; MODULE_DEVICE_TABLE (pci, i810_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/i2c/busses/i2c-piix4.c linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-piix4.c --- linux-2.6.22.19/drivers/i2c/busses/i2c-piix4.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-piix4.c 2008-03-04 08:55:59.000000000 +0100 @@ -113,7 +113,7 @@ static struct dmi_system_id __devinitdat .ident = "IBM", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, }, - { }, + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL }, }; static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, @@ -411,7 +411,7 @@ static struct pci_device_id piix4_ids[] .driver_data = 3 }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), .driver_data = 0 }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE (pci, piix4_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/i2c/busses/i2c-sis630.c linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-sis630.c --- linux-2.6.22.19/drivers/i2c/busses/i2c-sis630.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-sis630.c 2008-03-04 08:55:59.000000000 +0100 @@ -465,7 +465,7 @@ static struct i2c_adapter sis630_adapter static struct pci_device_id sis630_ids[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, - { 0, } + { PCI_DEVICE(0, 0) } }; MODULE_DEVICE_TABLE (pci, sis630_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/i2c/busses/i2c-sis96x.c linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-sis96x.c --- linux-2.6.22.19/drivers/i2c/busses/i2c-sis96x.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/i2c/busses/i2c-sis96x.c 2008-03-04 08:55:59.000000000 +0100 @@ -255,7 +255,7 @@ static struct i2c_adapter sis96x_adapter static struct pci_device_id sis96x_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, - { 0, } + { PCI_DEVICE(0, 0) } }; MODULE_DEVICE_TABLE (pci, sis96x_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/ide/ide-cd.c linux-2.6.22.19-g-v/drivers/ide/ide-cd.c --- linux-2.6.22.19/drivers/ide/ide-cd.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ide/ide-cd.c 2008-03-04 08:55:59.000000000 +0100 @@ -457,8 +457,6 @@ void cdrom_analyze_sense_data(ide_drive_ sector &= ~(bio_sectors -1); valid = (sector - failed_command->sector) << 9; - if (valid < 0) - valid = 0; if (sector < get_capacity(info->disk) && drive->probed_capacity - sector < 4 * 75) { set_capacity(info->disk, sector); diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/dv1394.c linux-2.6.22.19-g-v/drivers/ieee1394/dv1394.c --- linux-2.6.22.19/drivers/ieee1394/dv1394.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/dv1394.c 2008-03-04 08:55:59.000000000 +0100 @@ -739,7 +739,7 @@ static void frame_prepare(struct video_c based upon DIF section and sequence */ -static void inline +static inline void frame_put_packet (struct frame *f, struct packet *p) { int section_type = p->data[0] >> 5; /* section type is in bits 5 - 7 */ @@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_c /* default SYT offset is 3 cycles */ init->syt_offset = 3; - if ( (init->channel > 63) || (init->channel < 0) ) + if (init->channel > 63) init->channel = 63; chan_mask = (u64)1 << init->channel; @@ -2173,7 +2173,7 @@ static struct ieee1394_device_id dv1394_ .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = AVC_SW_VERSION_ENTRY & 0xffffff }, - { } + { 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/eth1394.c linux-2.6.22.19-g-v/drivers/ieee1394/eth1394.c --- linux-2.6.22.19/drivers/ieee1394/eth1394.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/eth1394.c 2008-03-04 08:55:59.000000000 +0100 @@ -449,7 +449,7 @@ static struct ieee1394_device_id eth1394 .specifier_id = ETHER1394_GASP_SPECIFIER_ID, .version = ETHER1394_GASP_VERSION, }, - {} + { 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table); diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/hosts.c linux-2.6.22.19-g-v/drivers/ieee1394/hosts.c --- linux-2.6.22.19/drivers/ieee1394/hosts.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/hosts.c 2008-03-04 08:55:59.000000000 +0100 @@ -78,6 +78,7 @@ static int dummy_isoctl(struct hpsb_iso } static struct hpsb_host_driver dummy_driver = { + .name = "dummy", .transmit_packet = dummy_transmit_packet, .devctl = dummy_devctl, .isoctl = dummy_isoctl diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/ohci1394.c linux-2.6.22.19-g-v/drivers/ieee1394/ohci1394.c --- linux-2.6.22.19/drivers/ieee1394/ohci1394.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/ohci1394.c 2008-03-04 08:55:59.000000000 +0100 @@ -160,9 +160,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_ printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) /* Module Parameters */ -static int phys_dma = 1; +static int phys_dma; module_param(phys_dma, int, 0444); -MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1)."); +MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 0)."); static void dma_trm_tasklet(unsigned long data); static void dma_trm_reset(struct dma_trm_ctx *d); @@ -3632,7 +3632,7 @@ static struct pci_device_id ohci1394_pci .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, - { 0, }, + { 0, 0, 0, 0, 0, 0, 0 }, }; MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl); diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/raw1394.c linux-2.6.22.19-g-v/drivers/ieee1394/raw1394.c --- linux-2.6.22.19/drivers/ieee1394/raw1394.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/raw1394.c 2008-03-04 08:55:59.000000000 +0100 @@ -3013,7 +3013,7 @@ static struct ieee1394_device_id raw1394 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff}, - {} + { 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/sbp2.c linux-2.6.22.19-g-v/drivers/ieee1394/sbp2.c --- linux-2.6.22.19/drivers/ieee1394/sbp2.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/sbp2.c 2008-03-04 08:55:59.000000000 +0100 @@ -273,7 +273,7 @@ static struct ieee1394_device_id sbp2_id .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, - {} + { 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); @@ -2131,7 +2131,7 @@ MODULE_DESCRIPTION("IEEE-1394 SBP-2 prot MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); MODULE_LICENSE("GPL"); -static int sbp2_module_init(void) +static int __init sbp2_module_init(void) { int ret; diff -NurpP --minimal linux-2.6.22.19/drivers/ieee1394/video1394.c linux-2.6.22.19-g-v/drivers/ieee1394/video1394.c --- linux-2.6.22.19/drivers/ieee1394/video1394.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/ieee1394/video1394.c 2008-03-04 08:55:59.000000000 +0100 @@ -893,7 +893,7 @@ static long video1394_ioctl(struct file if (unlikely(d == NULL)) return -EFAULT; - if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) { + if (unlikely(v.buffer>=d->num_desc - 1)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -959,7 +959,7 @@ static long video1394_ioctl(struct file if (unlikely(d == NULL)) return -EFAULT; - if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) { + if (unlikely(v.buffer>d->num_desc - 1)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if (d == NULL) return -EFAULT; - if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) { + if (v.buffer>=d->num_desc - 1) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if (d == NULL) return -EFAULT; - if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) { + if (v.buffer>=d->num_desc-1) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1309,7 +1309,7 @@ static struct ieee1394_device_id video13 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff }, - { } + { 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); diff -NurpP --minimal linux-2.6.22.19/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-2.6.22.19-g-v/drivers/infiniband/hw/ipath/ipath_user_pages.c --- linux-2.6.22.19/drivers/infiniband/hw/ipath/ipath_user_pages.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/infiniband/hw/ipath/ipath_user_pages.c 2008-03-04 08:55:59.000000000 +0100 @@ -33,6 +33,7 @@ #include #include +#include #include "ipath_kernel.h" @@ -61,7 +62,8 @@ static int __get_user_pages(unsigned lon lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; - if (num_pages > lock_limit) { + if (num_pages > lock_limit || + !vx_vmlocked_avail(current->mm, num_pages)) { ret = -ENOMEM; goto bail; } @@ -78,7 +80,7 @@ static int __get_user_pages(unsigned lon goto bail_release; } - current->mm->locked_vm += num_pages; + vx_vmlocked_add(current->mm, num_pages); ret = 0; goto bail; @@ -203,7 +205,7 @@ void ipath_release_user_pages(struct pag __ipath_release_user_pages(p, num_pages, 1); - current->mm->locked_vm -= num_pages; + vx_vmlocked_sub(current->mm, num_pages); up_write(¤t->mm->mmap_sem); } @@ -220,7 +222,7 @@ static void user_pages_account(struct wo container_of(_work, struct ipath_user_pages_work, work); down_write(&work->mm->mmap_sem); - work->mm->locked_vm -= work->num_pages; + vx_vmlocked_sub(work->mm, work->num_pages); up_write(&work->mm->mmap_sem); mmput(work->mm); kfree(work); diff -NurpP --minimal linux-2.6.22.19/drivers/input/keyboard/atkbd.c linux-2.6.22.19-g-v/drivers/input/keyboard/atkbd.c --- linux-2.6.22.19/drivers/input/keyboard/atkbd.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/keyboard/atkbd.c 2008-03-04 08:55:59.000000000 +0100 @@ -1075,7 +1075,7 @@ static struct serio_device_id atkbd_seri .id = SERIO_ANY, .extra = SERIO_ANY, }, - { 0 } + { 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(serio, atkbd_serio_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/input/mouse/lifebook.c linux-2.6.22.19-g-v/drivers/input/mouse/lifebook.c --- linux-2.6.22.19/drivers/input/mouse/lifebook.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/mouse/lifebook.c 2008-03-04 08:55:59.000000000 +0100 @@ -102,7 +102,7 @@ static struct dmi_system_id lifebook_dmi DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL} }; static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) diff -NurpP --minimal linux-2.6.22.19/drivers/input/mouse/psmouse-base.c linux-2.6.22.19-g-v/drivers/input/mouse/psmouse-base.c --- linux-2.6.22.19/drivers/input/mouse/psmouse-base.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/mouse/psmouse-base.c 2008-03-04 08:55:59.000000000 +0100 @@ -1296,7 +1296,7 @@ static struct serio_device_id psmouse_se .id = SERIO_ANY, .extra = SERIO_ANY, }, - { 0 } + { 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(serio, psmouse_serio_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/input/mouse/synaptics.c linux-2.6.22.19-g-v/drivers/input/mouse/synaptics.c --- linux-2.6.22.19/drivers/input/mouse/synaptics.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/mouse/synaptics.c 2008-03-04 08:55:59.000000000 +0100 @@ -417,7 +417,7 @@ static void synaptics_process_packet(str break; case 2: if (SYN_MODEL_PEN(priv->model_id)) - ; /* Nothing, treat a pen as a single finger */ + break; /* Nothing, treat a pen as a single finger */ break; case 4 ... 15: if (SYN_CAP_PALMDETECT(priv->capabilities)) @@ -624,7 +624,7 @@ static struct dmi_system_id toshiba_dmi_ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; #endif diff -NurpP --minimal linux-2.6.22.19/drivers/input/mousedev.c linux-2.6.22.19-g-v/drivers/input/mousedev.c --- linux-2.6.22.19/drivers/input/mousedev.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/mousedev.c 2008-03-04 08:55:59.000000000 +0100 @@ -815,7 +815,7 @@ static struct input_handler mousedev_han #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX static struct miscdevice psaux_mouse = { - PSMOUSE_MINOR, "psaux", &mousedev_fops + PSMOUSE_MINOR, "psaux", &mousedev_fops, {NULL, NULL}, NULL, NULL }; static int psaux_registered; #endif diff -NurpP --minimal linux-2.6.22.19/drivers/input/serio/i8042-x86ia64io.h linux-2.6.22.19-g-v/drivers/input/serio/i8042-x86ia64io.h --- linux-2.6.22.19/drivers/input/serio/i8042-x86ia64io.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/serio/i8042-x86ia64io.h 2008-03-04 08:55:59.000000000 +0100 @@ -110,7 +110,7 @@ static struct dmi_system_id __initdata i DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; /* @@ -252,7 +252,7 @@ static struct dmi_system_id __initdata i DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), }, }, - { } + { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL } }; diff -NurpP --minimal linux-2.6.22.19/drivers/input/serio/serio_raw.c linux-2.6.22.19-g-v/drivers/input/serio/serio_raw.c --- linux-2.6.22.19/drivers/input/serio/serio_raw.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/input/serio/serio_raw.c 2008-03-04 08:55:59.000000000 +0100 @@ -369,7 +369,7 @@ static struct serio_device_id serio_raw_ .id = SERIO_ANY, .extra = SERIO_ANY, }, - { 0 } + { 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/kvm/kvm_main.c linux-2.6.22.19-g-v/drivers/kvm/kvm_main.c --- linux-2.6.22.19/drivers/kvm/kvm_main.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/kvm/kvm_main.c 2008-03-04 08:56:00.000000000 +0100 @@ -60,19 +60,19 @@ static struct kvm_stats_debugfs_item { int offset; struct dentry *dentry; } debugfs_entries[] = { - { "pf_fixed", STAT_OFFSET(pf_fixed) }, - { "pf_guest", STAT_OFFSET(pf_guest) }, - { "tlb_flush", STAT_OFFSET(tlb_flush) }, - { "invlpg", STAT_OFFSET(invlpg) }, - { "exits", STAT_OFFSET(exits) }, - { "io_exits", STAT_OFFSET(io_exits) }, - { "mmio_exits", STAT_OFFSET(mmio_exits) }, - { "signal_exits", STAT_OFFSET(signal_exits) }, - { "irq_window", STAT_OFFSET(irq_window_exits) }, - { "halt_exits", STAT_OFFSET(halt_exits) }, - { "request_irq", STAT_OFFSET(request_irq_exits) }, - { "irq_exits", STAT_OFFSET(irq_exits) }, - { NULL } + { "pf_fixed", STAT_OFFSET(pf_fixed), NULL }, + { "pf_guest", STAT_OFFSET(pf_guest), NULL }, + { "tlb_flush", STAT_OFFSET(tlb_flush), NULL }, + { "invlpg", STAT_OFFSET(invlpg), NULL }, + { "exits", STAT_OFFSET(exits), NULL }, + { "io_exits", STAT_OFFSET(io_exits), NULL }, + { "mmio_exits", STAT_OFFSET(mmio_exits), NULL }, + { "signal_exits", STAT_OFFSET(signal_exits), NULL }, + { "irq_window", STAT_OFFSET(irq_window_exits), NULL }, + { "halt_exits", STAT_OFFSET(halt_exits), NULL }, + { "request_irq", STAT_OFFSET(request_irq_exits), NULL }, + { "irq_exits", STAT_OFFSET(irq_exits), NULL }, + { NULL, NULL, NULL } }; static struct dentry *debugfs_dir; @@ -2193,7 +2193,7 @@ static int kvm_vcpu_ioctl_translate(stru static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) { - if (irq->irq < 0 || irq->irq >= 256) + if (irq->irq >= 256) return -EINVAL; vcpu_load(vcpu); @@ -2851,6 +2851,9 @@ static struct miscdevice kvm_dev = { KVM_MINOR, "kvm", &kvm_chardev_ops, + {NULL, NULL}, + NULL, + NULL }; static int kvm_reboot(struct notifier_block *notifier, unsigned long val, diff -NurpP --minimal linux-2.6.22.19/drivers/kvm/vmx.c linux-2.6.22.19-g-v/drivers/kvm/vmx.c --- linux-2.6.22.19/drivers/kvm/vmx.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/kvm/vmx.c 2008-03-04 08:56:00.000000000 +0100 @@ -2013,7 +2013,7 @@ again: vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; - asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); + asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__KERNEL_DS)); if (fail) { kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY; diff -NurpP --minimal linux-2.6.22.19/drivers/md/bitmap.c linux-2.6.22.19-g-v/drivers/md/bitmap.c --- linux-2.6.22.19/drivers/md/bitmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/md/bitmap.c 2008-03-04 08:56:00.000000000 +0100 @@ -57,7 +57,7 @@ # if DEBUG > 0 # define PRINTK(x...) printk(KERN_DEBUG x) # else -# define PRINTK(x...) +# define PRINTK(x...) do {} while (0) # endif #endif diff -NurpP --minimal linux-2.6.22.19/drivers/md/dm-ioctl.c linux-2.6.22.19-g-v/drivers/md/dm-ioctl.c --- linux-2.6.22.19/drivers/md/dm-ioctl.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/md/dm-ioctl.c 2008-03-04 08:56:00.000000000 +0100 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -100,7 +101,8 @@ static struct hash_cell *__get_name_cell unsigned int h = hash_str(str); list_for_each_entry (hc, _name_buckets + h, name_list) - if (!strcmp(hc->name, str)) { + if (vx_check(dm_get_xid(hc->md), VS_WATCH_P | VS_IDENT) && + !strcmp(hc->name, str)) { dm_get(hc->md); return hc; } @@ -114,7 +116,8 @@ static struct hash_cell *__get_uuid_cell unsigned int h = hash_str(str); list_for_each_entry (hc, _uuid_buckets + h, uuid_list) - if (!strcmp(hc->uuid, str)) { + if (vx_check(dm_get_xid(hc->md), VS_WATCH_P | VS_IDENT) && + !strcmp(hc->uuid, str)) { dm_get(hc->md); return hc; } @@ -349,6 +352,9 @@ typedef int (*ioctl_fn)(struct dm_ioctl static int remove_all(struct dm_ioctl *param, size_t param_size) { + if (!vx_check(0, VS_ADMIN)) + return -EPERM; + dm_hash_remove_all(1); param->data_size = 0; return 0; @@ -396,6 +402,8 @@ static int list_devices(struct dm_ioctl */ for (i = 0; i < NUM_BUCKETS; i++) { list_for_each_entry (hc, _name_buckets + i, name_list) { + if (!vx_check(dm_get_xid(hc->md), VS_WATCH_P | VS_IDENT)) + continue; needed += sizeof(struct dm_name_list); needed += strlen(hc->name) + 1; needed += ALIGN_MASK; @@ -419,6 +427,8 @@ static int list_devices(struct dm_ioctl */ for (i = 0; i < NUM_BUCKETS; i++) { list_for_each_entry (hc, _name_buckets + i, name_list) { + if (!vx_check(dm_get_xid(hc->md), VS_WATCH_P | VS_IDENT)) + continue; if (old_nl) old_nl->next = (uint32_t) ((void *) nl - (void *) old_nl); @@ -609,10 +619,11 @@ static struct hash_cell *__find_device_h if (!md) goto out; - mdptr = dm_get_mdptr(md); + if (vx_check(dm_get_xid(md), VS_WATCH_P | VS_IDENT)) + mdptr = dm_get_mdptr(md); + if (!mdptr) dm_put(md); - out: return mdptr; } @@ -1409,8 +1420,8 @@ static int ctl_ioctl(struct inode *inode ioctl_fn fn = NULL; size_t param_size; - /* only root can play with this */ - if (!capable(CAP_SYS_ADMIN)) + /* only root and certain contexts can play with this */ + if (!vx_capable(CAP_SYS_ADMIN, VXC_ADMIN_MAPPER)) return -EACCES; if (_IOC_TYPE(command) != DM_IOCTL) diff -NurpP --minimal linux-2.6.22.19/drivers/md/dm.c linux-2.6.22.19-g-v/drivers/md/dm.c --- linux-2.6.22.19/drivers/md/dm.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/md/dm.c 2008-03-04 08:56:00.000000000 +0100 @@ -21,6 +21,7 @@ #include #include #include +#include #define DM_MSG_PREFIX "core" @@ -77,6 +78,7 @@ struct mapped_device { rwlock_t map_lock; atomic_t holders; atomic_t open_count; + xid_t xid; unsigned long flags; @@ -223,6 +225,7 @@ static void __exit dm_exit(void) static int dm_blk_open(struct inode *inode, struct file *file) { struct mapped_device *md; + int ret = -ENXIO; spin_lock(&_minor_lock); @@ -231,18 +234,19 @@ static int dm_blk_open(struct inode *ino goto out; if (test_bit(DMF_FREEING, &md->flags) || - test_bit(DMF_DELETING, &md->flags)) { - md = NULL; + test_bit(DMF_DELETING, &md->flags)) + goto out; + + ret = -EACCES; + if (!vx_check(md->xid, VS_IDENT|VS_HOSTID)) goto out; - } dm_get(md); atomic_inc(&md->open_count); - + ret = 0; out: spin_unlock(&_minor_lock); - - return md ? 0 : -ENXIO; + return ret; } static int dm_blk_close(struct inode *inode, struct file *file) @@ -438,6 +442,14 @@ int dm_set_geometry(struct mapped_device return 0; } +/* + * Get the xid associated with a dm device + */ +xid_t dm_get_xid(struct mapped_device *md) +{ + return md->xid; +} + /*----------------------------------------------------------------- * CRUD START: * A more elegant soln is in the works that uses the queue @@ -1000,6 +1012,7 @@ static struct mapped_device *alloc_dev(i atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); atomic_set(&md->event_nr, 0); + md->xid = vx_current_xid(); md->queue = blk_alloc_queue(GFP_KERNEL); if (!md->queue) diff -NurpP --minimal linux-2.6.22.19/drivers/md/dm.h linux-2.6.22.19-g-v/drivers/md/dm.h --- linux-2.6.22.19/drivers/md/dm.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/md/dm.h 2008-03-04 08:56:00.000000000 +0100 @@ -91,6 +91,8 @@ void dm_put_target_type(struct target_ty int dm_target_iterate(void (*iter_func)(struct target_type *tt, void *param), void *param); +xid_t dm_get_xid(struct mapped_device *md); + /*----------------------------------------------------------------- * Useful inlines. *---------------------------------------------------------------*/ diff -NurpP --minimal linux-2.6.22.19/drivers/mtd/devices/doc2001.c linux-2.6.22.19-g-v/drivers/mtd/devices/doc2001.c --- linux-2.6.22.19/drivers/mtd/devices/doc2001.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/mtd/devices/doc2001.c 2008-03-04 08:56:00.000000000 +0100 @@ -398,6 +398,8 @@ static int doc_read (struct mtd_info *mt /* Don't allow read past end of device */ if (from >= this->totlen) return -EINVAL; + if (!len) + return -EINVAL; /* Don't allow a single read to cross a 512-byte block boundary */ if (from + len > ((from | 0x1ff) + 1)) diff -NurpP --minimal linux-2.6.22.19/drivers/net/eepro100.c linux-2.6.22.19-g-v/drivers/net/eepro100.c --- linux-2.6.22.19/drivers/net/eepro100.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/net/eepro100.c 2008-03-04 08:56:00.000000000 +0100 @@ -47,7 +47,7 @@ static int rxdmacount /* = 0 */; # define rx_align(skb) skb_reserve((skb), 2) # define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed)) #else -# define rx_align(skb) +# define rx_align(skb) do {} while (0) # define RxFD_ALIGNMENT #endif @@ -2339,33 +2339,33 @@ static void __devexit eepro100_remove_on } static struct pci_device_id eepro100_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, }, - { 0,} + { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl); diff -NurpP --minimal linux-2.6.22.19/drivers/net/pcnet32.c linux-2.6.22.19-g-v/drivers/net/pcnet32.c --- linux-2.6.22.19/drivers/net/pcnet32.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/net/pcnet32.c 2008-03-04 08:56:00.000000000 +0100 @@ -82,7 +82,7 @@ static int cards_found; /* * VLB I/O addresses */ -static unsigned int pcnet32_portlist[] __initdata = +static unsigned int pcnet32_portlist[] __devinitdata = { 0x300, 0x320, 0x340, 0x360, 0 }; static int pcnet32_debug = 0; diff -NurpP --minimal linux-2.6.22.19/drivers/net/tg3.h linux-2.6.22.19-g-v/drivers/net/tg3.h --- linux-2.6.22.19/drivers/net/tg3.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/net/tg3.h 2008-03-04 08:56:00.000000000 +0100 @@ -127,6 +127,7 @@ #define CHIPREV_ID_5750_A0 0x4000 #define CHIPREV_ID_5750_A1 0x4001 #define CHIPREV_ID_5750_A3 0x4003 +#define CHIPREV_ID_5750_C1 0x4201 #define CHIPREV_ID_5750_C2 0x4202 #define CHIPREV_ID_5752_A0_HW 0x5000 #define CHIPREV_ID_5752_A0 0x6000 diff -NurpP --minimal linux-2.6.22.19/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.22.19-g-v/drivers/pci/hotplug/cpqphp_nvram.c --- linux-2.6.22.19/drivers/pci/hotplug/cpqphp_nvram.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pci/hotplug/cpqphp_nvram.c 2008-03-04 08:56:00.000000000 +0100 @@ -425,9 +425,13 @@ static u32 store_HRT (void __iomem *rom_ void compaq_nvram_init (void __iomem *rom_start) { + +#ifndef CONFIG_PAX_KERNEXEC if (rom_start) { compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); } +#endif + dbg("int15 entry = %p\n", compaq_int15_entry_point); /* initialize our int15 lock */ diff -NurpP --minimal linux-2.6.22.19/drivers/pci/pcie/aer/aerdrv.c linux-2.6.22.19-g-v/drivers/pci/pcie/aer/aerdrv.c --- linux-2.6.22.19/drivers/pci/pcie/aer/aerdrv.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pci/pcie/aer/aerdrv.c 2008-03-04 08:56:00.000000000 +0100 @@ -58,7 +58,7 @@ static struct pcie_port_service_id aer_i .port_type = PCIE_RC_PORT, .service_type = PCIE_PORT_SERVICE_AER, }, - { /* end: all zeroes */ } + { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; static struct pci_error_handlers aer_error_handlers = { diff -NurpP --minimal linux-2.6.22.19/drivers/pci/pcie/aer/aerdrv_core.c linux-2.6.22.19-g-v/drivers/pci/pcie/aer/aerdrv_core.c --- linux-2.6.22.19/drivers/pci/pcie/aer/aerdrv_core.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pci/pcie/aer/aerdrv_core.c 2008-03-04 08:56:00.000000000 +0100 @@ -647,7 +647,7 @@ static void aer_isr_one_error(struct pci struct aer_err_source *e_src) { struct device *s_device; - struct aer_err_info e_info = {0, 0, 0,}; + struct aer_err_info e_info = {0, 0, 0, {0, 0, 0, 0}}; int i; u16 id; diff -NurpP --minimal linux-2.6.22.19/drivers/pci/pcie/portdrv_pci.c linux-2.6.22.19-g-v/drivers/pci/pcie/portdrv_pci.c --- linux-2.6.22.19/drivers/pci/pcie/portdrv_pci.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pci/pcie/portdrv_pci.c 2008-03-04 08:56:00.000000000 +0100 @@ -265,7 +265,7 @@ static void pcie_portdrv_err_resume(stru static const struct pci_device_id port_pci_ids[] = { { /* handle any PCI-Express port */ PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), - }, { /* end: all zeroes */ } + }, { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, port_pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/pci/proc.c linux-2.6.22.19-g-v/drivers/pci/proc.c --- linux-2.6.22.19/drivers/pci/proc.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pci/proc.c 2008-03-04 08:56:00.000000000 +0100 @@ -466,7 +466,15 @@ static int __init pci_proc_init(void) { 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 -NurpP --minimal linux-2.6.22.19/drivers/pcmcia/ti113x.h linux-2.6.22.19-g-v/drivers/pcmcia/ti113x.h --- linux-2.6.22.19/drivers/pcmcia/ti113x.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pcmcia/ti113x.h 2008-03-04 08:56:00.000000000 +0100 @@ -897,7 +897,7 @@ static struct pci_device_id ene_tune_tbl DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID, ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), - {} + { 0, 0, 0, 0, 0, 0, 0 } }; static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) diff -NurpP --minimal linux-2.6.22.19/drivers/pcmcia/yenta_socket.c linux-2.6.22.19-g-v/drivers/pcmcia/yenta_socket.c --- linux-2.6.22.19/drivers/pcmcia/yenta_socket.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pcmcia/yenta_socket.c 2008-03-04 08:56:00.000000000 +0100 @@ -1358,7 +1358,7 @@ static struct pci_device_id yenta_table /* match any cardbus bridge */ CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), - { /* all zeroes */ } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, yenta_table); diff -NurpP --minimal linux-2.6.22.19/drivers/pnp/pnpbios/bioscalls.c linux-2.6.22.19-g-v/drivers/pnp/pnpbios/bioscalls.c --- linux-2.6.22.19/drivers/pnp/pnpbios/bioscalls.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pnp/pnpbios/bioscalls.c 2008-03-04 08:56:00.000000000 +0100 @@ -65,7 +65,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr set_limit(gdt[(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 @@ -93,6 +93,10 @@ static inline u16 call_pnp_bios(u16 func struct desc_struct save_desc_40; int cpu; +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + /* * PnP BIOSes are generally not terribly re-entrant. * Also, don't rely on them to save everything correctly. @@ -107,6 +111,10 @@ static inline u16 call_pnp_bios(u16 func /* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave(&pnp_bios_lock, flags); +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + /* The lock prevents us bouncing CPU here */ if (ts1_size) Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size); @@ -142,9 +150,14 @@ static inline u16 call_pnp_bios(u16 func "i" (0) : "memory" ); - spin_unlock_irqrestore(&pnp_bios_lock, flags); get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + + spin_unlock_irqrestore(&pnp_bios_lock, flags); put_cpu(); /* If we get here and this is set then the PnP BIOS faulted on us. */ @@ -515,15 +528,25 @@ static int pnp_bios_write_escd(char *dat * Initialization */ -void pnpbios_calls_init(union pnp_bios_install_struct *header) +void __init pnpbios_calls_init(union pnp_bios_install_struct *header) { int i; + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + spin_lock_init(&pnp_bios_lock); pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment = PNP_CS16; set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); +#endif + for (i = 0; i < NR_CPUS; i++) { struct desc_struct *gdt = get_cpu_gdt_table(i); if (!gdt) @@ -532,4 +555,9 @@ void pnpbios_calls_init(union pnp_bios_i set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg)); set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg)); } + +#ifdef CONFIG_PAX_KERNEXEC + pax_close_kernel(cr0); +#endif + } diff -NurpP --minimal linux-2.6.22.19/drivers/pnp/quirks.c linux-2.6.22.19-g-v/drivers/pnp/quirks.c --- linux-2.6.22.19/drivers/pnp/quirks.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pnp/quirks.c 2008-03-04 08:56:00.000000000 +0100 @@ -231,7 +231,7 @@ static struct pnp_fixup pnp_fixups[] = { { "CTL0044", quirk_sb16audio_resources }, { "CTL0045", quirk_sb16audio_resources }, { "SMCf010", quirk_smc_enable }, - { "" } + { "", NULL } }; void pnp_fixup_device(struct pnp_dev *dev) diff -NurpP --minimal linux-2.6.22.19/drivers/pnp/resource.c linux-2.6.22.19-g-v/drivers/pnp/resource.c --- linux-2.6.22.19/drivers/pnp/resource.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/pnp/resource.c 2008-03-04 08:56:00.000000000 +0100 @@ -364,7 +364,7 @@ int pnp_check_irq(struct pnp_dev * dev, return 1; /* check if the resource is valid */ - if (*irq < 0 || *irq > 15) + if (*irq > 15) return 0; /* check if the resource is reserved */ @@ -430,7 +430,7 @@ int pnp_check_dma(struct pnp_dev * dev, return 1; /* check if the resource is valid */ - if (*dma < 0 || *dma == 4 || *dma > 7) + if (*dma == 4 || *dma > 7) return 0; /* check if the resource is reserved */ diff -NurpP --minimal linux-2.6.22.19/drivers/scsi/scsi_lib.c linux-2.6.22.19-g-v/drivers/scsi/scsi_lib.c --- linux-2.6.22.19/drivers/scsi/scsi_lib.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/scsi/scsi_lib.c 2008-03-04 08:56:00.000000000 +0100 @@ -44,7 +44,7 @@ struct scsi_host_sg_pool { #error SCSI_MAX_PHYS_SEGMENTS is too small #endif -#define SP(x) { x, "sgpool-" #x } +#define SP(x) { x, "sgpool-" #x, NULL, NULL } static struct scsi_host_sg_pool scsi_sg_pools[] = { SP(8), SP(16), diff -NurpP --minimal linux-2.6.22.19/drivers/scsi/scsi_logging.h linux-2.6.22.19-g-v/drivers/scsi/scsi_logging.h --- linux-2.6.22.19/drivers/scsi/scsi_logging.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/scsi/scsi_logging.h 2008-03-04 08:56:00.000000000 +0100 @@ -51,7 +51,7 @@ do { \ } while (0); \ } while (0) #else -#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) +#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) do {} while (0) #endif /* CONFIG_SCSI_LOGGING */ /* diff -NurpP --minimal linux-2.6.22.19/drivers/serial/8250_pci.c linux-2.6.22.19-g-v/drivers/serial/8250_pci.c --- linux-2.6.22.19/drivers/serial/8250_pci.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/serial/8250_pci.c 2008-03-04 08:56:00.000000000 +0100 @@ -2417,7 +2417,7 @@ static struct pci_device_id serial_pci_t PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, pbn_default }, - { 0, } + { 0, 0, 0, 0, 0, 0, 0 } }; static struct pci_driver serial_pci_driver = { diff -NurpP --minimal linux-2.6.22.19/drivers/usb/class/cdc-acm.c linux-2.6.22.19-g-v/drivers/usb/class/cdc-acm.c --- linux-2.6.22.19/drivers/usb/class/cdc-acm.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/class/cdc-acm.c 2008-03-04 08:56:00.000000000 +0100 @@ -1194,7 +1194,7 @@ static struct usb_device_id acm_ids[] = USB_CDC_ACM_PROTO_AT_CDMA) }, /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */ - { } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE (usb, acm_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/usb/class/usblp.c linux-2.6.22.19-g-v/drivers/usb/class/usblp.c --- linux-2.6.22.19/drivers/usb/class/usblp.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/class/usblp.c 2008-03-04 08:56:00.000000000 +0100 @@ -219,7 +219,7 @@ static const struct quirk_printer_struct { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut */ { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ - { 0, 0 } + { 0, 0, 0 } }; static int usblp_select_alts(struct usblp *usblp); @@ -1234,7 +1234,7 @@ static struct usb_device_id usblp_ids [] { USB_INTERFACE_INFO(7, 1, 2) }, { USB_INTERFACE_INFO(7, 1, 3) }, { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */ - { } /* Terminating entry */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, usblp_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/usb/core/hub.c linux-2.6.22.19-g-v/drivers/usb/core/hub.c --- linux-2.6.22.19/drivers/usb/core/hub.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/core/hub.c 2008-03-04 08:56:00.000000000 +0100 @@ -2848,7 +2848,7 @@ static struct usb_device_id hub_id_table .bDeviceClass = USB_CLASS_HUB}, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, .bInterfaceClass = USB_CLASS_HUB}, - { } /* Terminating entry */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, hub_id_table); diff -NurpP --minimal linux-2.6.22.19/drivers/usb/host/ehci-pci.c linux-2.6.22.19-g-v/drivers/usb/host/ehci-pci.c --- linux-2.6.22.19/drivers/usb/host/ehci-pci.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/host/ehci-pci.c 2008-03-04 08:56:00.000000000 +0100 @@ -377,7 +377,7 @@ static const struct pci_device_id pci_id PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), .driver_data = (unsigned long) &ehci_pci_hc_driver, }, - { /* end: all zeroes */ } + { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/usb/host/uhci-hcd.c linux-2.6.22.19-g-v/drivers/usb/host/uhci-hcd.c --- linux-2.6.22.19/drivers/usb/host/uhci-hcd.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/host/uhci-hcd.c 2008-03-04 08:56:00.000000000 +0100 @@ -895,7 +895,7 @@ static const struct pci_device_id uhci_p /* handle any USB UHCI controller */ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0), .driver_data = (unsigned long) &uhci_driver, - }, { /* end: all zeroes */ } + }, { 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE(pci, uhci_pci_ids); diff -NurpP --minimal linux-2.6.22.19/drivers/usb/storage/debug.h linux-2.6.22.19-g-v/drivers/usb/storage/debug.h --- linux-2.6.22.19/drivers/usb/storage/debug.h 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/storage/debug.h 2008-03-04 08:56:00.000000000 +0100 @@ -56,9 +56,9 @@ void usb_stor_show_sense( unsigned char #define US_DEBUGPX(x...) printk( x ) #define US_DEBUG(x) x #else -#define US_DEBUGP(x...) -#define US_DEBUGPX(x...) -#define US_DEBUG(x) +#define US_DEBUGP(x...) do {} while (0) +#define US_DEBUGPX(x...) do {} while (0) +#define US_DEBUG(x) do {} while (0) #endif #endif diff -NurpP --minimal linux-2.6.22.19/drivers/usb/storage/usb.c linux-2.6.22.19-g-v/drivers/usb/storage/usb.c --- linux-2.6.22.19/drivers/usb/storage/usb.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/usb/storage/usb.c 2008-03-04 08:56:00.000000000 +0100 @@ -141,7 +141,7 @@ static struct usb_device_id storage_usb_ #undef UNUSUAL_DEV #undef USUAL_DEV /* Terminating entry */ - { } + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; MODULE_DEVICE_TABLE (usb, storage_usb_ids); @@ -181,7 +181,7 @@ static struct us_unusual_dev us_unusual_ # undef USUAL_DEV /* Terminating entry */ - { NULL } + { NULL, NULL, 0, 0, NULL } }; diff -NurpP --minimal linux-2.6.22.19/drivers/video/fbcmap.c linux-2.6.22.19-g-v/drivers/video/fbcmap.c --- linux-2.6.22.19/drivers/video/fbcmap.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/fbcmap.c 2008-03-04 08:56:00.000000000 +0100 @@ -251,8 +251,7 @@ int fb_set_user_cmap(struct fb_cmap_user int rc, size = cmap->len * sizeof(u16); struct fb_cmap umap; - if (cmap->start < 0 || (!info->fbops->fb_setcolreg && - !info->fbops->fb_setcmap)) + if (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap) return -EINVAL; memset(&umap, 0, sizeof(struct fb_cmap)); diff -NurpP --minimal linux-2.6.22.19/drivers/video/fbmem.c linux-2.6.22.19-g-v/drivers/video/fbmem.c --- linux-2.6.22.19/drivers/video/fbmem.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/fbmem.c 2008-03-04 08:56:00.000000000 +0100 @@ -392,7 +392,7 @@ static void fb_do_show_logo(struct fb_in image->dx += image->width + 8; } } else if (rotate == FB_ROTATE_UD) { - for (x = 0; x < num && image->dx >= 0; x++) { + for (x = 0; x < num && (__s32)image->dx >= 0; x++) { info->fbops->fb_imageblit(info, image); image->dx -= image->width + 8; } @@ -404,7 +404,7 @@ static void fb_do_show_logo(struct fb_in image->dy += image->height + 8; } } else if (rotate == FB_ROTATE_CCW) { - for (x = 0; x < num && image->dy >= 0; x++) { + for (x = 0; x < num && (__s32)image->dy >= 0; x++) { info->fbops->fb_imageblit(info, image); image->dy -= image->height + 8; } @@ -973,9 +973,9 @@ fb_ioctl(struct inode *inode, struct fil case FBIOPUT_CON2FBMAP: if (copy_from_user(&con2fb, argp, sizeof(con2fb))) return - EFAULT; - if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES) + if (con2fb.console > MAX_NR_CONSOLES) return -EINVAL; - if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) + if (con2fb.framebuffer >= FB_MAX) return -EINVAL; #ifdef CONFIG_KMOD if (!registered_fb[con2fb.framebuffer]) diff -NurpP --minimal linux-2.6.22.19/drivers/video/fbmon.c linux-2.6.22.19-g-v/drivers/video/fbmon.c --- linux-2.6.22.19/drivers/video/fbmon.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/fbmon.c 2008-03-04 08:56:00.000000000 +0100 @@ -45,7 +45,7 @@ #ifdef DEBUG #define DPRINTK(fmt, args...) printk(fmt,## args) #else -#define DPRINTK(fmt, args...) +#define DPRINTK(fmt, args...) do {} while (0) #endif #define FBMON_FIX_HEADER 1 diff -NurpP --minimal linux-2.6.22.19/drivers/video/i810/i810_accel.c linux-2.6.22.19-g-v/drivers/video/i810/i810_accel.c --- linux-2.6.22.19/drivers/video/i810/i810_accel.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/i810/i810_accel.c 2008-03-04 08:56:00.000000000 +0100 @@ -73,6 +73,7 @@ static inline int wait_for_space(struct } } printk("ringbuffer lockup!!!\n"); + printk("head:%u tail:%u iring.size:%u space:%u\n", head, tail, par->iring.size, space); i810_report_error(mmio); par->dev_flags |= LOCKUP; info->pixmap.scan_align = 1; diff -NurpP --minimal linux-2.6.22.19/drivers/video/i810/i810_main.c linux-2.6.22.19-g-v/drivers/video/i810/i810_main.c --- linux-2.6.22.19/drivers/video/i810/i810_main.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/i810/i810_main.c 2008-03-04 08:56:00.000000000 +0100 @@ -120,7 +120,7 @@ static struct pci_device_id i810fb_pci_t PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { 0 }, + { 0, 0, 0, 0, 0, 0, 0 }, }; static struct pci_driver i810fb_driver = { @@ -1509,7 +1509,7 @@ static int i810fb_cursor(struct fb_info int size = ((cursor->image.width + 7) >> 3) * cursor->image.height; int i; - u8 *data = kmalloc(64 * 8, GFP_ATOMIC); + u8 *data = kmalloc(64 * 8, GFP_KERNEL); if (data == NULL) return -ENOMEM; diff -NurpP --minimal linux-2.6.22.19/drivers/video/modedb.c linux-2.6.22.19-g-v/drivers/video/modedb.c --- linux-2.6.22.19/drivers/video/modedb.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/modedb.c 2008-03-04 08:56:00.000000000 +0100 @@ -37,228 +37,228 @@ static const struct fb_videomode modedb[ { /* 640x400 @ 70 Hz, 31.5 kHz hsync */ NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x480 @ 60 Hz, 31.5 kHz hsync */ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 800x600 @ 56 Hz, 35.15 kHz hsync */ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, - 0, FB_VMODE_INTERLACED + 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x400 @ 85 Hz, 37.86 kHz hsync */ NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, - FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x480 @ 72 Hz, 36.5 kHz hsync */ NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x480 @ 75 Hz, 37.50 kHz hsync */ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 800x600 @ 60 Hz, 37.8 kHz hsync */ NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x480 @ 85 Hz, 43.27 kHz hsync */ NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, - 0, FB_VMODE_INTERLACED + 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN }, { /* 800x600 @ 72 Hz, 48.0 kHz hsync */ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 640x480 @ 100 Hz, 53.01 kHz hsync */ NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 800x600 @ 85 Hz, 55.84 kHz hsync */ NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, - 0, FB_VMODE_INTERLACED + 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN }, { /* 800x600 @ 100 Hz, 64.02 kHz hsync */ NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1024x768 @ 100Hz, 80.21 kHz hsync */ NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 512x384 @ 78 Hz, 31.50 kHz hsync */ NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 512x384 @ 85 Hz, 34.38 kHz hsync */ NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 320x240 @ 72 Hz, 36.5 kHz hsync */ NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 400x300 @ 60 Hz, 37.8 kHz hsync */ NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 400x300 @ 72 Hz, 48.0 kHz hsync */ NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 480x300 @ 60 Hz, 37.8 kHz hsync */ NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 480x300 @ 63 Hz, 39.6 kHz hsync */ NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 480x300 @ 72 Hz, 48.0 kHz hsync */ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, - 0, FB_VMODE_DOUBLE + 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN }, { /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, - FB_VMODE_NONINTERLACED + FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, { /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, - 0, FB_VMODE_NONINTERLACED + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN }, }; diff -NurpP --minimal linux-2.6.22.19/drivers/video/vesafb.c linux-2.6.22.19-g-v/drivers/video/vesafb.c --- linux-2.6.22.19/drivers/video/vesafb.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/drivers/video/vesafb.c 2008-03-04 08:56:00.000000000 +0100 @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -224,6 +225,7 @@ static int __init vesafb_probe(struct pl unsigned int size_vmode; unsigned int size_remap; unsigned int size_total; + void *pmi_code = NULL; if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return -ENODEV; @@ -266,10 +268,6 @@ static int __init vesafb_probe(struct pl size_remap = size_total; vesafb_fix.smem_len = size_remap; -#ifndef __i386__ - screen_info.vesapm_seg = 0; -#endif - if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) { printk(KERN_WARNING "vesafb: cannot reserve video memory at 0x%lx\n", @@ -302,9 +300,21 @@ static int __init vesafb_probe(struct pl printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); +#ifdef __i386__ + +#ifdef CONFIG_PAX_KERNEXEC + pmi_code = module_alloc_exec(screen_info.vesapm_size); + if (!pmi_code) +#else + if (0) +#endif + +#endif + screen_info.vesapm_seg = 0; + if (screen_info.vesapm_seg) { - printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", - screen_info.vesapm_seg,screen_info.vesapm_off); + printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x %04x bytes\n", + screen_info.vesapm_seg,screen_info.vesapm_off,screen_info.vesapm_size); } if (screen_info.vesapm_seg < 0xc000) @@ -312,9 +322,29 @@ static int __init vesafb_probe(struct pl if (ypan || pmi_setpal) { unsigned short *pmi_base; - pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); - pmi_start = (void*)((char*)pmi_base + pmi_base[1]); - pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); + +#ifdef CONFIG_PAX_KERNEXEC + unsigned long cr0; +#endif + + pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); + +#ifdef CONFIG_PAX_KERNEXEC + pax_open_kernel(cr0); + memcpy(pmi_code, pmi_base, screen_info.vesapm_size); + pax_close_kernel(cr0); +#else + pmi_code = pmi_base; +#endif + + pmi_start = (void*)((char*)pmi_code + pmi_base[1]); + pmi_pal = (void*)((char*)pmi_code + pmi_base[2]); + +#ifdef CONFIG_PAX_KERNEXEC + pmi_start -= __KERNEL_TEXT_OFFSET; + pmi_pal -= __KERNEL_TEXT_OFFSET; +#endif + printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal); if (pmi_base[3]) { printk(KERN_INFO "vesafb: pmi: ports = "); @@ -456,6 +486,11 @@ static int __init vesafb_probe(struct pl info->node, info->fix.id); return 0; err: + +#ifdef CONFIG_PAX_KERNEXEC + module_free_exec(NULL, pmi_code); +#endif + if (info->screen_base) iounmap(info->screen_base); framebuffer_release(info); diff -NurpP --minimal linux-2.6.22.19/fs/Kconfig linux-2.6.22.19-g-v/fs/Kconfig --- linux-2.6.22.19/fs/Kconfig 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/fs/Kconfig 2008-03-04 08:56:00.000000000 +0100 @@ -912,7 +912,7 @@ config PROC_FS config PROC_KCORE bool "/proc/kcore support" if !ARM - depends on PROC_FS && MMU + depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD config PROC_VMCORE bool "/proc/vmcore support (EXPERIMENTAL)" @@ -2026,7 +2026,7 @@ config CODA_FS_OLD_API config AFS_FS tristate "Andrew File System support (AFS) (EXPERIMENTAL)" - depends on INET && EXPERIMENTAL + depends on INET && EXPERIMENTAL && !VSERVER_SECURITY select AF_RXRPC help If you say Y here, you will get an experimental Andrew File System diff -NurpP --minimal linux-2.6.22.19/fs/attr.c linux-2.6.22.19-g-v/fs/attr.c --- linux-2.6.22.19/fs/attr.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/fs/attr.c 2008-03-04 08:56:00.000000000 +0100 @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include /* Taken over from the old code... */ @@ -55,6 +58,27 @@ int inode_change_ok(struct inode *inode, if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) goto error; } + + /* Check for evil vserver activity */ + if (vx_check(0, VS_ADMIN)) + goto fine; + + if (IS_BARRIER(inode)) { + vxwprintk_task(1, "messing with the barrier."); + goto error; + } + switch (inode->i_sb->s_magic) { + case PROC_SUPER_MAGIC: + /* maybe allow that in the future? */ + vxwprintk_task(1, "messing with the procfs."); + goto error; + case DEVPTS_SUPER_MAGIC: + /* devpts is xid tagged */ + if (vx_check((xid_t)inode->i_tag, VS_IDENT)) + goto fine; + vxwprintk_task(1, "messing with the devpts."); + goto error; + } fine: retval = 0; error: @@ -78,6 +102,8 @@ int inode_setattr(struct inode * inode, inode->i_uid = attr->ia_uid; if (ia_valid & ATTR_GID) inode->i_gid = attr->ia_gid; + if ((ia_valid & ATTR_TAG) && IS_TAGGED(inode)) + inode->i_tag = attr->ia_tag; if (ia_valid & ATTR_ATIME) inode->i_atime = timespec_trunc(attr->ia_atime, inode->i_sb->s_time_gran); @@ -152,7 +178,8 @@ int notify_change(struct dentry * dentry error = security_inode_setattr(dentry, attr); if (!error) { if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || - (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) + (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid) || + (ia_valid & ATTR_TAG && attr->ia_tag != inode->i_tag)) error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; if (!error) error = inode_setattr(inode, attr); diff -NurpP --minimal linux-2.6.22.19/fs/binfmt_aout.c linux-2.6.22.19-g-v/fs/binfmt_aout.c --- linux-2.6.22.19/fs/binfmt_aout.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/fs/binfmt_aout.c 2008-03-04 08:56:00.000000000 +0100 @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -123,10 +125,12 @@ static int aout_core_dump(long signr, st /* 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->signal->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->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_dsize = 0; @@ -134,10 +138,12 @@ static int aout_core_dump(long signr, st /* 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->signal->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->signal->rlim[RLIMIT_CORE].rlim_cur) dump.u_ssize = 0; @@ -294,6 +300,8 @@ static int load_aout_binary(struct linux rlim = current->signal->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; @@ -326,6 +334,28 @@ static int load_aout_binary(struct linux current->mm->mmap = NULL; compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; + +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) + current->mm->pax_flags = 0UL; +#endif + +#ifdef CONFIG_PAX_PAGEEXEC + if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) { + current->mm->pax_flags |= MF_PAX_PAGEEXEC; + +#ifdef CONFIG_PAX_EMUTRAMP + if (N_FLAGS(ex) & F_PAX_EMUTRAMP) + current->mm->pax_flags |= MF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_PAX_MPROTECT + if (!(N_FLAGS(ex) & F_PAX_MPROTECT)) + current->mm->pax_flags |= MF_PAX_MPROTECT; +#endif + + } +#endif + #ifdef __sparc__ if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; @@ -421,7 +451,7 @@ static int load_aout_binary(struct linux 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 -NurpP --minimal linux-2.6.22.19/fs/binfmt_elf.c linux-2.6.22.19-g-v/fs/binfmt_elf.c --- linux-2.6.22.19/fs/binfmt_elf.c 2008-02-26 00:59:40.000000000 +0100 +++ linux-2.6.22.19-g-v/fs/binfmt_elf.c 2008-03-04 08:56:00.000000000 +0100 @@ -39,10 +39,22 @@ #include #include #include +#include +#include + #include #include #include +#ifdef CONFIG_PAX_SEGMEXEC +#include +#endif + +#ifdef CONFIG_PAX_HOOK_ACL_FLAGS +void (*pax_set_initial_flags_func)(struct linux_binprm *bprm); +EXPORT_SYMBOL(pax_set_initial_flags_func); +#endif + static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); static int load_elf_library(struct file *); static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); @@ -84,6 +96,8 @@ static struct linux_binfmt elf_format = static int set_brk(unsigned long start, unsigned long end) { + unsigned long e = end; + start = ELF_PAGEALIGN(start); end = ELF_PAGEALIGN(end); if (end > start) { @@ -94,7 +108,7 @@ static int set_brk(unsigned long start, if (BAD_ADDR(addr)) return addr; } - current->mm->start_brk = current->mm->brk = end; + current->mm->start_brk = current->mm->brk = e; return 0; } @@ -315,10 +329,9 @@ static unsigned long load_elf_interp(str { struct elf_phdr *elf_phdata; struct elf_phdr *eppnt; - unsigned long load_addr = 0; - int load_addr_set = 0; + unsigned long load_addr = 0, min_addr, max_addr, task_size = TASK_SIZE; unsigned long last_bss = 0, elf_bss = 0; - unsigned long error = ~0UL; + unsigned long error = -EINVAL; int retval, i, size; /* First of all, some simple consistency checks */ @@ -357,66 +370,86 @@ static unsigned long load_elf_interp(str goto out_close; } +#ifdef CONFIG_PAX_SEGMEXEC + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) + task_size = SEGMEXEC_TASK_SIZE; +#endif + eppnt = elf_phdata; + min_addr = task_size; + max_addr = 0; + error = -ENOMEM; + for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { - if (eppnt->p_type == PT_LOAD) { - int elf_type = MAP_PRIVATE | MAP_DENYWRITE; - int elf_prot = 0; - unsigned long vaddr = 0; - unsigned long k, map_addr; + if (eppnt->p_type != PT_LOAD) + continue; - if (eppnt->p_flags & PF_R) - elf_prot = PROT_READ; - if (eppnt->p_flags & PF_W) - elf_prot |= PROT_WRITE; - if (eppnt->p_flags & PF_X) - elf_prot |= PROT_EXEC; - vaddr = eppnt->p_vaddr; - if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) - elf_type |= MAP_FIXED; + /* + * Check to see if the section's size will overflow the + * allowed task size. Note that p_filesz must always be + * <= p_memsize so it is only necessary to check p_memsz. + */ + if (eppnt->p_filesz > eppnt->p_memsz || eppnt->p_vaddr >= eppnt->p_vaddr + eppnt->p_memsz) + goto out_close; - map_addr = elf_map(interpreter, load_addr + vaddr, - eppnt, elf_prot, elf_type); - error = map_addr; - if (BAD_ADDR(map_addr)) - goto out_close; + if (min_addr > ELF_PAGESTART(eppnt->p_vaddr)) + min_addr = ELF_PAGESTART(eppnt->p_vaddr); + if (max_addr < ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz)) + max_addr = ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz); + } + if (min_addr >= max_addr || max_addr > task_size) + goto out_close; - if (!load_addr_set && - interp_elf_ex->e_type == ET_DYN) { - load_addr = map_addr - ELF_PAGESTART(vaddr); - load_addr_set = 1; - } + if (interp_elf_ex->e_type == ET_DYN) { + load_addr = get_unmapped_area(interpreter, 0, max_addr - min_addr, 0, MAP_PRIVATE | MAP_EXECUTABLE); - /* - * Check to see if the section's size will overflow the - * allowed task size. Note that p_filesz must always be - * <= p_memsize so it's only necessary to check p_memsz. - */ - k = load_addr + eppnt->p_vaddr; - if (BAD_ADDR(k) || - eppnt->p_filesz > eppnt->p_memsz || - eppnt->p_memsz > TASK_SIZE || - TASK_SIZE - eppnt->p_memsz < k) { - error = -ENOMEM; - goto out_close; - } + if (load_addr >= task_size) + goto out_close; - /* - * Find the end of the file mapping for this phdr, and - * keep track of the largest address we see for this. - */ - k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; - if (k > elf_bss) - elf_bss = k; + load_addr -= min_addr; + } - /* - * Do the same thing for the memory mapping - between - * elf_bss and last_bss is the bss section. - */ - k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; - if (k > last_bss) - last_bss = k; - } + eppnt = elf_phdata; + for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { + int elf_type = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED; + int elf_prot = 0; + unsigned long vaddr = 0; + unsigned long k, map_addr; + + if (eppnt->p_type != PT_LOAD) + continue; + + if (eppnt->p_flags & PF_R) + elf_prot = PROT_READ; + if (eppnt->p_flags & PF_W) + elf_prot |= PROT_WRITE; + if (eppnt->p_flags & PF_X) + elf_prot |= PROT_EXEC; + vaddr = eppnt->p_vaddr; + + map_addr = elf_map(interpreter, load_addr + vaddr, + eppnt, elf_prot, elf_type); + error = map_addr; + if (BAD_ADDR(map_addr)) + goto out_close; + + k = load_addr + eppnt->p_vaddr; + + /* + * Find the end of the file mapping for this phdr, and + * keep track of the largest address we see for this. + */ + k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; + if (k > elf_bss) + elf_bss = k; + + /* + * Do the same thing for the memory mapping - between + * elf_bss and last_bss is the bss section. + */ + k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; + if (k > last_bss) + last_bss = k; } /* @@ -444,6 +477,8 @@ static unsigned long load_elf_interp(str *interp_load_addr = load_addr; error = ((unsigned long)interp_elf_ex->e_entry) + load_addr; + if (BAD_ADDR(error)) + error = -EFAULT; out_close: kfree(elf_phdata); @@ -454,7 +489,7 @@ out: static unsigned long load_aout_interp(struct exec *interp_ex, struct file *interpreter) { - unsigned long text_data, elf_entry = ~0UL; + unsigned long text_data, elf_entry = -EINVAL; char __user * addr; loff_t offset; @@ -497,6 +532,177 @@ out: 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 |= MF_PAX_PAGEEXEC; +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if (elf_phdata->p_flags & PF_SEGMEXEC) + pax_flags |= MF_PAX_SEGMEXEC; +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + if (nx_enabled) + pax_flags &= ~MF_PAX_SEGMEXEC; + else + pax_flags &= ~MF_PAX_PAGEEXEC; + } +#endif + +#ifdef CONFIG_PAX_EMUTRAMP + if (elf_phdata->p_flags & PF_EMUTRAMP) + pax_flags |= MF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_PAX_MPROTECT + if (elf_phdata->p_flags & PF_MPROTECT) + pax_flags |= MF_PAX_MPROTECT; +#endif + +#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) + if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP)) + pax_flags |= MF_PAX_RANDMMAP; +#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 |= MF_PAX_PAGEEXEC; +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if (!(elf_phdata->p_flags & PF_NOSEGMEXEC)) + pax_flags |= MF_PAX_SEGMEXEC; +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + if (nx_enabled) + pax_flags &= ~MF_PAX_SEGMEXEC; + else + pax_flags &= ~MF_PAX_PAGEEXEC; + } +#endif + +#ifdef CONFIG_PAX_EMUTRAMP + if (!(elf_phdata->p_flags & PF_NOEMUTRAMP)) + pax_flags |= MF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_PAX_MPROTECT + if (!(elf_phdata->p_flags & PF_NOMPROTECT)) + pax_flags |= MF_PAX_MPROTECT; +#endif + +#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) + if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP)) + pax_flags |= MF_PAX_RANDMMAP; +#endif + + return pax_flags; +} +#endif + +#ifdef CONFIG_PAX_EI_PAX +static unsigned long 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 |= MF_PAX_PAGEEXEC; +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC)) + pax_flags |= MF_PAX_SEGMEXEC; +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + if (nx_enabled) + pax_flags &= ~MF_PAX_SEGMEXEC; + else + pax_flags &= ~MF_PAX_PAGEEXEC; + } +#endif + +#ifdef CONFIG_PAX_EMUTRAMP + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP)) + pax_flags |= MF_PAX_EMUTRAMP; +#endif + +#ifdef CONFIG_PAX_MPROTECT + if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT)) + pax_flags |= MF_PAX_MPROTECT; +#endif + +#ifdef CONFIG_PAX_ASLR + if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP)) + pax_flags |= MF_PAX_RANDMMAP; +#endif + + return pax_flags; +} +#endif + +#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) +static long 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))) + 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->mm->pax_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. @@ -534,7 +740,7 @@ static int load_elf_binary(struct linux_ char * elf_interpreter = NULL; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter = 0; - unsigned long error; + unsigned long error = 0; struct elf_phdr *elf_ppnt, *elf_phdata; unsigned long elf_bss, elf_brk; int elf_exec_fileno; @@ -546,12 +752,12 @@ static int load_elf_binary(struct linux_ char passed_fileno[6]; struct files_struct *files; int executable_stack = EXSTACK_DEFAULT; - unsigned long def_flags = 0; struct { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; } *loc; + unsigned long task_size = TASK_SIZE; loc = kmalloc(sizeof(*loc), GFP_KERNEL); if (!loc) { @@ -782,14 +988,89 @@ static int load_elf_binary(struct linux_ current->mm->end_code = 0; current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; - current->mm->def_flags = def_flags; + +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) + current->mm->pax_flags = 0UL; +#endif + +#ifdef CONFIG_PAX_DLRESOLVE + current->mm->call_dl_resolve = 0UL; +#endif + +#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT) + current->mm->call_syscall = 0UL; +#endif + +#ifdef CONFIG_PAX_ASLR + current->mm->delta_mmap = 0UL; + current->mm->delta_stack = 0UL; +#endif + + current->mm->def_flags = 0; + +#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) + if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) { + send_sig(SIGKILL, current, 0); + goto out_free_dentry; + } +#endif + +#ifdef CONFIG_PAX_HAVE_ACL_FLAGS + pax_set_initial_flags(bprm); +#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS) + if (pax_set_initial_flags_func) + (pax_set_initial_flags_func)(bprm); +#endif + +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT + if ((current->mm->pax_flags & MF_PAX_PAGEEXEC) && !nx_enabled) { + current->mm->context.user_cs_limit = PAGE_SIZE; + current->mm->def_flags |= VM_PAGEEXEC; + } +#endif + +#ifdef CONFIG_PAX_SEGMEXEC + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) { + current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE; + current->mm->context.user_cs_limit = TASK_SIZE-SEGMEXEC_TASK_SIZE; + task_size = SEGMEXEC_TASK_SIZE; + } +#endif + +#if defined(CONFIG_ARCH_TRACK_EXEC_LIMIT) || defined(CONFIG_PAX_SEGMEXEC) + if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { + set_user_cs(current->mm->context.user_cs_base, current->mm->context.user_cs_limit, get_cpu()); + put_cpu_no_resched(); + } +#endif + +#ifdef CONFIG_PAX_ASLR + if (current->mm->pax_flags & MF_PAX_RANDMMAP) { + current->mm->delta_mmap = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN)-1)) << PAGE_SHIFT; + current->mm->delta_stack = (pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT; + } +#endif + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) + executable_stack = EXSTACK_DEFAULT; +#endif /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter); + +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) + if (!(current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))) +#endif + if (elf_read_implies_exec(loc->elf_ex, executable_stack)) current->personality |= READ_IMPLIES_EXEC; +#ifdef CONFIG_PAX_ASLR + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) current->flags |= PF_RANDOMIZE; arch_pick_mmap_layout(current->mm); @@ -865,6 +1146,20 @@ static int load_elf_binary(struct linux_ * 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->mm->pax_flags & MF_PAX_RANDMMAP) && elf_interpreter) { +#ifdef CONFIG_SPARC64 + load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << (PAGE_SHIFT+1); +#else + load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << PAGE_SHIFT; +#endif + load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE - vaddr + load_bias); + elf_flags |= MAP_FIXED; + } +#endif + } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, @@ -897,9 +1192,9 @@ static int load_elf_binary(struct linux_ * allowed task size. Note that p_filesz must always be * <= p_memsz so it is only necessary to check p_memsz. */ - if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || - elf_ppnt->p_memsz > TASK_SIZE || - TASK_SIZE - elf_ppnt->p_memsz < k) { + if (k >= task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz || + elf_ppnt->p_memsz > task_size || + task_size - elf_ppnt->p_memsz < k) { /* set_brk can never work. Avoid overflows. */ send_sig(SIGKILL, current, 0); retval = -EINVAL; @@ -927,6 +1222,11 @@ static int load_elf_binary(struct linux_ start_data += load_bias; end_data += load_bias; +#ifdef CONFIG_PAX_RANDMMAP + if (current->mm->pax_flags & MF_PAX_RANDMMAP) + elf_brk += PAGE_SIZE + ((pax_get_random_long() & ~PAGE_MASK) << 4); +#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 @@ -938,9 +1238,11 @@ static int load_elf_binary(struct li