forked from Minki/linux
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
This commit is contained in:
commit
01565479e9
@ -28,11 +28,11 @@ unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *re
|
|||||||
struct desc_struct *desc;
|
struct desc_struct *desc;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
|
|
||||||
seg &= ~7UL;
|
seg >>= 3;
|
||||||
|
|
||||||
mutex_lock(&child->mm->context.lock);
|
mutex_lock(&child->mm->context.lock);
|
||||||
if (unlikely(!child->mm->context.ldt ||
|
if (unlikely(!child->mm->context.ldt ||
|
||||||
(seg >> 3) >= child->mm->context.ldt->size))
|
seg >= child->mm->context.ldt->size))
|
||||||
addr = -1L; /* bogus selector, access would fault */
|
addr = -1L; /* bogus selector, access would fault */
|
||||||
else {
|
else {
|
||||||
desc = &child->mm->context.ldt->entries[seg];
|
desc = &child->mm->context.ldt->entries[seg];
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/desc.h>
|
|
||||||
#include <asm/user.h>
|
#include <asm/user.h>
|
||||||
#include <asm/fpu/internal.h>
|
#include <asm/fpu/internal.h>
|
||||||
|
|
||||||
@ -181,7 +180,7 @@ void math_emulate(struct math_emu_info *info)
|
|||||||
math_abort(FPU_info, SIGILL);
|
math_abort(FPU_info, SIGILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
code_descriptor = LDT_DESCRIPTOR(FPU_CS);
|
code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
|
||||||
if (SEG_D_SIZE(code_descriptor)) {
|
if (SEG_D_SIZE(code_descriptor)) {
|
||||||
/* The above test may be wrong, the book is not clear */
|
/* The above test may be wrong, the book is not clear */
|
||||||
/* Segmented 32 bit protected mode */
|
/* Segmented 32 bit protected mode */
|
||||||
|
@ -16,9 +16,24 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
|
||||||
/* s is always from a cpu register, and the cpu does bounds checking
|
#include <asm/desc.h>
|
||||||
* during register load --> no further bounds checks needed */
|
#include <asm/mmu_context.h>
|
||||||
#define LDT_DESCRIPTOR(s) (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
|
|
||||||
|
static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg)
|
||||||
|
{
|
||||||
|
static struct desc_struct zero_desc;
|
||||||
|
struct desc_struct ret = zero_desc;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
||||||
|
seg >>= 3;
|
||||||
|
mutex_lock(¤t->mm->context.lock);
|
||||||
|
if (current->mm->context.ldt && seg < current->mm->context.ldt->size)
|
||||||
|
ret = current->mm->context.ldt->entries[seg];
|
||||||
|
mutex_unlock(¤t->mm->context.lock);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#define SEG_D_SIZE(x) ((x).b & (3 << 21))
|
#define SEG_D_SIZE(x) ((x).b & (3 << 21))
|
||||||
#define SEG_G_BIT(x) ((x).b & (1 << 23))
|
#define SEG_G_BIT(x) ((x).b & (1 << 23))
|
||||||
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
|
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <linux/stddef.h>
|
#include <linux/stddef.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/desc.h>
|
|
||||||
|
|
||||||
#include "fpu_system.h"
|
#include "fpu_system.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
@ -158,7 +157,7 @@ static long pm_address(u_char FPU_modrm, u_char segment,
|
|||||||
addr->selector = PM_REG_(segment);
|
addr->selector = PM_REG_(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
|
descriptor = FPU_get_ldt_descriptor(addr->selector);
|
||||||
base_address = SEG_BASE_ADDR(descriptor);
|
base_address = SEG_BASE_ADDR(descriptor);
|
||||||
address = base_address + offset;
|
address = base_address + offset;
|
||||||
limit = base_address
|
limit = base_address
|
||||||
|
Loading…
Reference in New Issue
Block a user