diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-31 02:31:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-31 02:31:57 -0500 |
commit | a9de18eb761f7c1c860964b2e5addc1a35c7e861 (patch) | |
tree | 886e75fdfd09690cd262ca69cb7f5d1d42b48602 /arch/x86/mm/fault.c | |
parent | b2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (diff) | |
parent | 6a94cb73064c952255336cc57731904174b2c58f (diff) |
Merge branch 'linus' into stackprotector
Conflicts:
arch/x86/include/asm/pda.h
kernel/fork.c
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r-- | arch/x86/mm/fault.c | 60 |
1 files changed, 26 insertions, 34 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index d18ea136d8a..4c056b5d6a9 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -54,7 +54,7 @@ | |||
54 | 54 | ||
55 | static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr) | 55 | static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr) |
56 | { | 56 | { |
57 | #ifdef CONFIG_MMIOTRACE_HOOKS | 57 | #ifdef CONFIG_MMIOTRACE |
58 | if (unlikely(is_kmmio_active())) | 58 | if (unlikely(is_kmmio_active())) |
59 | if (kmmio_handler(regs, addr) == 1) | 59 | if (kmmio_handler(regs, addr) == 1) |
60 | return -1; | 60 | return -1; |
@@ -394,7 +394,7 @@ static void show_fault_oops(struct pt_regs *regs, unsigned long error_code, | |||
394 | if (pte && pte_present(*pte) && !pte_exec(*pte)) | 394 | if (pte && pte_present(*pte) && !pte_exec(*pte)) |
395 | printk(KERN_CRIT "kernel tried to execute " | 395 | printk(KERN_CRIT "kernel tried to execute " |
396 | "NX-protected page - exploit attempt? " | 396 | "NX-protected page - exploit attempt? " |
397 | "(uid: %d)\n", current->uid); | 397 | "(uid: %d)\n", current_uid()); |
398 | } | 398 | } |
399 | #endif | 399 | #endif |
400 | 400 | ||
@@ -414,6 +414,7 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, | |||
414 | unsigned long error_code) | 414 | unsigned long error_code) |
415 | { | 415 | { |
416 | unsigned long flags = oops_begin(); | 416 | unsigned long flags = oops_begin(); |
417 | int sig = SIGKILL; | ||
417 | struct task_struct *tsk; | 418 | struct task_struct *tsk; |
418 | 419 | ||
419 | printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", | 420 | printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", |
@@ -424,8 +425,8 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, | |||
424 | tsk->thread.trap_no = 14; | 425 | tsk->thread.trap_no = 14; |
425 | tsk->thread.error_code = error_code; | 426 | tsk->thread.error_code = error_code; |
426 | if (__die("Bad pagetable", regs, error_code)) | 427 | if (__die("Bad pagetable", regs, error_code)) |
427 | regs = NULL; | 428 | sig = 0; |
428 | oops_end(flags, regs, SIGKILL); | 429 | oops_end(flags, regs, sig); |
429 | } | 430 | } |
430 | #endif | 431 | #endif |
431 | 432 | ||
@@ -593,6 +594,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
593 | 594 | ||
594 | #ifdef CONFIG_X86_64 | 595 | #ifdef CONFIG_X86_64 |
595 | unsigned long flags; | 596 | unsigned long flags; |
597 | int sig; | ||
596 | #endif | 598 | #endif |
597 | 599 | ||
598 | tsk = current; | 600 | tsk = current; |
@@ -643,24 +645,23 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
643 | } | 645 | } |
644 | 646 | ||
645 | 647 | ||
646 | #ifdef CONFIG_X86_32 | ||
647 | /* It's safe to allow irq's after cr2 has been saved and the vmalloc | ||
648 | fault has been handled. */ | ||
649 | if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK)) | ||
650 | local_irq_enable(); | ||
651 | |||
652 | /* | 648 | /* |
653 | * If we're in an interrupt, have no user context or are running in an | 649 | * It's safe to allow irq's after cr2 has been saved and the |
654 | * atomic region then we must not take the fault. | 650 | * vmalloc fault has been handled. |
651 | * | ||
652 | * User-mode registers count as a user access even for any | ||
653 | * potential system fault or CPU buglet. | ||
655 | */ | 654 | */ |
656 | if (in_atomic() || !mm) | 655 | if (user_mode_vm(regs)) { |
657 | goto bad_area_nosemaphore; | 656 | local_irq_enable(); |
658 | #else /* CONFIG_X86_64 */ | 657 | error_code |= PF_USER; |
659 | if (likely(regs->flags & X86_EFLAGS_IF)) | 658 | } else if (regs->flags & X86_EFLAGS_IF) |
660 | local_irq_enable(); | 659 | local_irq_enable(); |
661 | 660 | ||
661 | #ifdef CONFIG_X86_64 | ||
662 | if (unlikely(error_code & PF_RSVD)) | 662 | if (unlikely(error_code & PF_RSVD)) |
663 | pgtable_bad(address, regs, error_code); | 663 | pgtable_bad(address, regs, error_code); |
664 | #endif | ||
664 | 665 | ||
665 | /* | 666 | /* |
666 | * If we're in an interrupt, have no user context or are running in an | 667 | * If we're in an interrupt, have no user context or are running in an |
@@ -669,15 +670,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
669 | if (unlikely(in_atomic() || !mm)) | 670 | if (unlikely(in_atomic() || !mm)) |
670 | goto bad_area_nosemaphore; | 671 | goto bad_area_nosemaphore; |
671 | 672 | ||
672 | /* | ||
673 | * User-mode registers count as a user access even for any | ||
674 | * potential system fault or CPU buglet. | ||
675 | */ | ||
676 | if (user_mode_vm(regs)) | ||
677 | error_code |= PF_USER; | ||
678 | again: | 673 | again: |
679 | #endif | 674 | /* |
680 | /* When running in the kernel we expect faults to occur only to | 675 | * When running in the kernel we expect faults to occur only to |
681 | * addresses in user space. All other faults represent errors in the | 676 | * addresses in user space. All other faults represent errors in the |
682 | * kernel and should generate an OOPS. Unfortunately, in the case of an | 677 | * kernel and should generate an OOPS. Unfortunately, in the case of an |
683 | * erroneous fault occurring in a code path which already holds mmap_sem | 678 | * erroneous fault occurring in a code path which already holds mmap_sem |
@@ -740,9 +735,6 @@ good_area: | |||
740 | goto bad_area; | 735 | goto bad_area; |
741 | } | 736 | } |
742 | 737 | ||
743 | #ifdef CONFIG_X86_32 | ||
744 | survive: | ||
745 | #endif | ||
746 | /* | 738 | /* |
747 | * If for any reason at all we couldn't handle the fault, | 739 | * If for any reason at all we couldn't handle the fault, |
748 | * make sure we exit gracefully rather than endlessly redo | 740 | * make sure we exit gracefully rather than endlessly redo |
@@ -866,11 +858,12 @@ no_context: | |||
866 | bust_spinlocks(0); | 858 | bust_spinlocks(0); |
867 | do_exit(SIGKILL); | 859 | do_exit(SIGKILL); |
868 | #else | 860 | #else |
861 | sig = SIGKILL; | ||
869 | if (__die("Oops", regs, error_code)) | 862 | if (__die("Oops", regs, error_code)) |
870 | regs = NULL; | 863 | sig = 0; |
871 | /* Executive summary in case the body of the oops scrolled away */ | 864 | /* Executive summary in case the body of the oops scrolled away */ |
872 | printk(KERN_EMERG "CR2: %016lx\n", address); | 865 | printk(KERN_EMERG "CR2: %016lx\n", address); |
873 | oops_end(flags, regs, SIGKILL); | 866 | oops_end(flags, regs, sig); |
874 | #endif | 867 | #endif |
875 | 868 | ||
876 | /* | 869 | /* |
@@ -881,12 +874,11 @@ out_of_memory: | |||
881 | up_read(&mm->mmap_sem); | 874 | up_read(&mm->mmap_sem); |
882 | if (is_global_init(tsk)) { | 875 | if (is_global_init(tsk)) { |
883 | yield(); | 876 | yield(); |
884 | #ifdef CONFIG_X86_32 | 877 | /* |
885 | down_read(&mm->mmap_sem); | 878 | * Re-lookup the vma - in theory the vma tree might |
886 | goto survive; | 879 | * have changed: |
887 | #else | 880 | */ |
888 | goto again; | 881 | goto again; |
889 | #endif | ||
890 | } | 882 | } |
891 | 883 | ||
892 | printk("VM: killing process %s\n", tsk->comm); | 884 | printk("VM: killing process %s\n", tsk->comm); |