diff options
| -rw-r--r-- | arch/i386/kernel/process.c | 73 | ||||
| -rw-r--r-- | include/asm-i386/processor.h | 4 | ||||
| -rw-r--r-- | include/asm-i386/thread_info.h | 5 | ||||
| -rw-r--r-- | include/linux/seccomp.h | 10 | ||||
| -rw-r--r-- | kernel/seccomp.c | 3 |
5 files changed, 50 insertions, 45 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 06dfa65ad18..6c49acb9698 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
| @@ -538,8 +538,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
| 538 | return 1; | 538 | return 1; |
| 539 | } | 539 | } |
| 540 | 540 | ||
| 541 | static noinline void __switch_to_xtra(struct task_struct *next_p, | 541 | #ifdef CONFIG_SECCOMP |
| 542 | struct tss_struct *tss) | 542 | void hard_disable_TSC(void) |
| 543 | { | ||
| 544 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 545 | } | ||
| 546 | void disable_TSC(void) | ||
| 547 | { | ||
| 548 | preempt_disable(); | ||
| 549 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
| 550 | /* | ||
| 551 | * Must flip the CPU state synchronously with | ||
| 552 | * TIF_NOTSC in the current running context. | ||
| 553 | */ | ||
| 554 | hard_disable_TSC(); | ||
| 555 | preempt_enable(); | ||
| 556 | } | ||
| 557 | void hard_enable_TSC(void) | ||
| 558 | { | ||
| 559 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 560 | } | ||
| 561 | #endif /* CONFIG_SECCOMP */ | ||
| 562 | |||
| 563 | static noinline void | ||
| 564 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
| 565 | struct tss_struct *tss) | ||
| 543 | { | 566 | { |
| 544 | struct thread_struct *next; | 567 | struct thread_struct *next; |
| 545 | 568 | ||
| @@ -555,6 +578,17 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
| 555 | set_debugreg(next->debugreg[7], 7); | 578 | set_debugreg(next->debugreg[7], 7); |
| 556 | } | 579 | } |
| 557 | 580 | ||
| 581 | #ifdef CONFIG_SECCOMP | ||
| 582 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
| 583 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
| 584 | /* prev and next are different */ | ||
| 585 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
| 586 | hard_disable_TSC(); | ||
| 587 | else | ||
| 588 | hard_enable_TSC(); | ||
| 589 | } | ||
| 590 | #endif | ||
| 591 | |||
| 558 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 592 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |
| 559 | /* | 593 | /* |
| 560 | * Disable the bitmap via an invalid offset. We still cache | 594 | * Disable the bitmap via an invalid offset. We still cache |
| @@ -586,33 +620,6 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
| 586 | } | 620 | } |
| 587 | 621 | ||
| 588 | /* | 622 | /* |
| 589 | * This function selects if the context switch from prev to next | ||
| 590 | * has to tweak the TSC disable bit in the cr4. | ||
| 591 | */ | ||
| 592 | static inline void disable_tsc(struct task_struct *prev_p, | ||
| 593 | struct task_struct *next_p) | ||
| 594 | { | ||
| 595 | struct thread_info *prev, *next; | ||
| 596 | |||
| 597 | /* | ||
| 598 | * gcc should eliminate the ->thread_info dereference if | ||
| 599 | * has_secure_computing returns 0 at compile time (SECCOMP=n). | ||
| 600 | */ | ||
| 601 | prev = task_thread_info(prev_p); | ||
| 602 | next = task_thread_info(next_p); | ||
| 603 | |||
| 604 | if (has_secure_computing(prev) || has_secure_computing(next)) { | ||
| 605 | /* slow path here */ | ||
| 606 | if (has_secure_computing(prev) && | ||
| 607 | !has_secure_computing(next)) { | ||
| 608 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 609 | } else if (!has_secure_computing(prev) && | ||
| 610 | has_secure_computing(next)) | ||
| 611 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 612 | } | ||
| 613 | } | ||
| 614 | |||
| 615 | /* | ||
| 616 | * switch_to(x,yn) should switch tasks from x to y. | 623 | * switch_to(x,yn) should switch tasks from x to y. |
| 617 | * | 624 | * |
| 618 | * We fsave/fwait so that an exception goes off at the right time | 625 | * We fsave/fwait so that an exception goes off at the right time |
| @@ -689,11 +696,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
| 689 | /* | 696 | /* |
| 690 | * Now maybe handle debug registers and/or IO bitmaps | 697 | * Now maybe handle debug registers and/or IO bitmaps |
| 691 | */ | 698 | */ |
| 692 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW) | 699 | if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV || |
| 693 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))) | 700 | task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT)) |
| 694 | __switch_to_xtra(next_p, tss); | 701 | __switch_to_xtra(prev_p, next_p, tss); |
| 695 | |||
| 696 | disable_tsc(prev_p, next_p); | ||
| 697 | 702 | ||
| 698 | /* | 703 | /* |
| 699 | * Leave lazy mode, flushing any hypercalls made here. | 704 | * Leave lazy mode, flushing any hypercalls made here. |
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 94e0c147c16..422cffef00c 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
| @@ -228,6 +228,10 @@ extern int bootloader_type; | |||
| 228 | 228 | ||
| 229 | #define HAVE_ARCH_PICK_MMAP_LAYOUT | 229 | #define HAVE_ARCH_PICK_MMAP_LAYOUT |
| 230 | 230 | ||
| 231 | extern void hard_disable_TSC(void); | ||
| 232 | extern void disable_TSC(void); | ||
| 233 | extern void hard_enable_TSC(void); | ||
| 234 | |||
| 231 | /* | 235 | /* |
| 232 | * Size of io_bitmap. | 236 | * Size of io_bitmap. |
| 233 | */ | 237 | */ |
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h index 4cb0f91ae64..54424e045e0 100644 --- a/include/asm-i386/thread_info.h +++ b/include/asm-i386/thread_info.h | |||
| @@ -137,6 +137,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 137 | #define TIF_DEBUG 17 /* uses debug registers */ | 137 | #define TIF_DEBUG 17 /* uses debug registers */ |
| 138 | #define TIF_IO_BITMAP 18 /* uses I/O bitmap */ | 138 | #define TIF_IO_BITMAP 18 /* uses I/O bitmap */ |
| 139 | #define TIF_FREEZE 19 /* is freezing for suspend */ | 139 | #define TIF_FREEZE 19 /* is freezing for suspend */ |
| 140 | #define TIF_NOTSC 20 /* TSC is not accessible in userland */ | ||
| 140 | 141 | ||
| 141 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 142 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
| 142 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | 143 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) |
| @@ -151,6 +152,7 @@ static inline struct thread_info *current_thread_info(void) | |||
| 151 | #define _TIF_DEBUG (1<<TIF_DEBUG) | 152 | #define _TIF_DEBUG (1<<TIF_DEBUG) |
| 152 | #define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) | 153 | #define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) |
| 153 | #define _TIF_FREEZE (1<<TIF_FREEZE) | 154 | #define _TIF_FREEZE (1<<TIF_FREEZE) |
| 155 | #define _TIF_NOTSC (1<<TIF_NOTSC) | ||
| 154 | 156 | ||
| 155 | /* work to do on interrupt/exception return */ | 157 | /* work to do on interrupt/exception return */ |
| 156 | #define _TIF_WORK_MASK \ | 158 | #define _TIF_WORK_MASK \ |
| @@ -160,7 +162,8 @@ static inline struct thread_info *current_thread_info(void) | |||
| 160 | #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) | 162 | #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) |
| 161 | 163 | ||
| 162 | /* flags to check in __switch_to() */ | 164 | /* flags to check in __switch_to() */ |
| 163 | #define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP) | 165 | #define _TIF_WORK_CTXSW_NEXT (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUG) |
| 166 | #define _TIF_WORK_CTXSW_PREV (_TIF_IO_BITMAP | _TIF_NOTSC) | ||
| 164 | 167 | ||
| 165 | /* | 168 | /* |
| 166 | * Thread-synchronous status. | 169 | * Thread-synchronous status. |
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index d708974dbfe..262a8dccfa8 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h | |||
| @@ -16,11 +16,6 @@ static inline void secure_computing(int this_syscall) | |||
| 16 | __secure_computing(this_syscall); | 16 | __secure_computing(this_syscall); |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | static inline int has_secure_computing(struct thread_info *ti) | ||
| 20 | { | ||
| 21 | return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP)); | ||
| 22 | } | ||
| 23 | |||
| 24 | extern long prctl_get_seccomp(void); | 19 | extern long prctl_get_seccomp(void); |
| 25 | extern long prctl_set_seccomp(unsigned long); | 20 | extern long prctl_set_seccomp(unsigned long); |
| 26 | 21 | ||
| @@ -29,11 +24,6 @@ extern long prctl_set_seccomp(unsigned long); | |||
| 29 | typedef struct { } seccomp_t; | 24 | typedef struct { } seccomp_t; |
| 30 | 25 | ||
| 31 | #define secure_computing(x) do { } while (0) | 26 | #define secure_computing(x) do { } while (0) |
| 32 | /* static inline to preserve typechecking */ | ||
| 33 | static inline int has_secure_computing(struct thread_info *ti) | ||
| 34 | { | ||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | 27 | ||
| 38 | static inline long prctl_get_seccomp(void) | 28 | static inline long prctl_get_seccomp(void) |
| 39 | { | 29 | { |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 1dfa8a50972..ad64fcb731f 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
| @@ -74,6 +74,9 @@ long prctl_set_seccomp(unsigned long seccomp_mode) | |||
| 74 | if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { | 74 | if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { |
| 75 | current->seccomp.mode = seccomp_mode; | 75 | current->seccomp.mode = seccomp_mode; |
| 76 | set_thread_flag(TIF_SECCOMP); | 76 | set_thread_flag(TIF_SECCOMP); |
| 77 | #ifdef TIF_NOTSC | ||
| 78 | disable_TSC(); | ||
| 79 | #endif | ||
| 77 | ret = 0; | 80 | ret = 0; |
| 78 | } | 81 | } |
| 79 | 82 | ||
