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 |