diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-16 18:11:25 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-16 18:11:25 -0400 |
| commit | 01565479e99882e873e4dd2f6f067b7cba3acf8f (patch) | |
| tree | 014de0c29378ef1380ab6bb48baca135468aca35 | |
| parent | 8ed1f0e22f49ef42e63875fd2529389a32ff3566 (diff) | |
| parent | 12e244f4b550498bbaf654a52f93633f7dde2dc7 (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Merge x86 fixes from Ingo Molnar:
"Two followup fixes related to the previous LDT fix"
Also applied a further FPU emulation fix from Andy Lutomirski to the
branch before actually merging it.
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
x86/ldt: Further fix FPU emulation
x86/ldt: Correct FPU emulation access to LDT
x86/ldt: Correct LDT access in single stepping logic
| -rw-r--r-- | arch/x86/kernel/step.c | 4 | ||||
| -rw-r--r-- | arch/x86/math-emu/fpu_entry.c | 3 | ||||
| -rw-r--r-- | arch/x86/math-emu/fpu_system.h | 21 | ||||
| -rw-r--r-- | arch/x86/math-emu/get_address.c | 3 |
4 files changed, 22 insertions, 9 deletions
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 6273324186ac..0ccb53a9fcd9 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c | |||
| @@ -28,11 +28,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re | |||
| 28 | struct desc_struct *desc; | 28 | struct desc_struct *desc; |
| 29 | unsigned long base; | 29 | unsigned long base; |
| 30 | 30 | ||
| 31 | seg &= ~7UL; | 31 | seg >>= 3; |
| 32 | 32 | ||
| 33 | mutex_lock(&child->mm->context.lock); | 33 | mutex_lock(&child->mm->context.lock); |
| 34 | if (unlikely(!child->mm->context.ldt || | 34 | if (unlikely(!child->mm->context.ldt || |
| 35 | (seg >> 3) >= child->mm->context.ldt->size)) | 35 | seg >= child->mm->context.ldt->size)) |
| 36 | addr = -1L; /* bogus selector, access would fault */ | 36 | addr = -1L; /* bogus selector, access would fault */ |
| 37 | else { | 37 | else { |
| 38 | desc = &child->mm->context.ldt->entries[seg]; | 38 | desc = &child->mm->context.ldt->entries[seg]; |
diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index f37e84ab49f3..3d8f2e421466 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
| 31 | #include <asm/traps.h> | 31 | #include <asm/traps.h> |
| 32 | #include <asm/desc.h> | ||
| 33 | #include <asm/user.h> | 32 | #include <asm/user.h> |
| 34 | #include <asm/fpu/internal.h> | 33 | #include <asm/fpu/internal.h> |
| 35 | 34 | ||
| @@ -181,7 +180,7 @@ void math_emulate(struct math_emu_info *info) | |||
| 181 | math_abort(FPU_info, SIGILL); | 180 | math_abort(FPU_info, SIGILL); |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | code_descriptor = LDT_DESCRIPTOR(FPU_CS); | 183 | code_descriptor = FPU_get_ldt_descriptor(FPU_CS); |
| 185 | if (SEG_D_SIZE(code_descriptor)) { | 184 | if (SEG_D_SIZE(code_descriptor)) { |
| 186 | /* The above test may be wrong, the book is not clear */ | 185 | /* The above test may be wrong, the book is not clear */ |
| 187 | /* Segmented 32 bit protected mode */ | 186 | /* Segmented 32 bit protected mode */ |
diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h index 9ccecb61a4fa..5e044d506b7a 100644 --- a/arch/x86/math-emu/fpu_system.h +++ b/arch/x86/math-emu/fpu_system.h | |||
| @@ -16,9 +16,24 @@ | |||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
| 18 | 18 | ||
| 19 | /* s is always from a cpu register, and the cpu does bounds checking | 19 | #include <asm/desc.h> |
| 20 | * during register load --> no further bounds checks needed */ | 20 | #include <asm/mmu_context.h> |
| 21 | #define LDT_DESCRIPTOR(s) (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3]) | 21 | |
| 22 | static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg) | ||
| 23 | { | ||
| 24 | static struct desc_struct zero_desc; | ||
| 25 | struct desc_struct ret = zero_desc; | ||
| 26 | |||
| 27 | #ifdef CONFIG_MODIFY_LDT_SYSCALL | ||
| 28 | seg >>= 3; | ||
| 29 | mutex_lock(¤t->mm->context.lock); | ||
| 30 | if (current->mm->context.ldt && seg < current->mm->context.ldt->size) | ||
| 31 | ret = current->mm->context.ldt->entries[seg]; | ||
| 32 | mutex_unlock(¤t->mm->context.lock); | ||
| 33 | #endif | ||
| 34 | return ret; | ||
| 35 | } | ||
| 36 | |||
| 22 | #define SEG_D_SIZE(x) ((x).b & (3 << 21)) | 37 | #define SEG_D_SIZE(x) ((x).b & (3 << 21)) |
| 23 | #define SEG_G_BIT(x) ((x).b & (1 << 23)) | 38 | #define SEG_G_BIT(x) ((x).b & (1 << 23)) |
| 24 | #define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1) | 39 | #define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1) |
diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c index 6ef5e99380f9..8300db71c2a6 100644 --- a/arch/x86/math-emu/get_address.c +++ b/arch/x86/math-emu/get_address.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
| 21 | 21 | ||
| 22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 23 | #include <asm/desc.h> | ||
| 24 | 23 | ||
| 25 | #include "fpu_system.h" | 24 | #include "fpu_system.h" |
| 26 | #include "exception.h" | 25 | #include "exception.h" |
| @@ -158,7 +157,7 @@ static long pm_address(u_char FPU_modrm, u_char segment, | |||
| 158 | addr->selector = PM_REG_(segment); | 157 | addr->selector = PM_REG_(segment); |
| 159 | } | 158 | } |
| 160 | 159 | ||
| 161 | descriptor = LDT_DESCRIPTOR(PM_REG_(segment)); | 160 | descriptor = FPU_get_ldt_descriptor(addr->selector); |
| 162 | base_address = SEG_BASE_ADDR(descriptor); | 161 | base_address = SEG_BASE_ADDR(descriptor); |
| 163 | address = base_address + offset; | 162 | address = base_address + offset; |
| 164 | limit = base_address | 163 | limit = base_address |
