x86/insn-eval: Add utility function to get segment descriptor
The segment descriptor contains information that is relevant to how linear addresses need to be computed. It contains the default size of addresses as well as the base address of the segment. Thus, given a segment selector, we ought to look at segment descriptor to correctly calculate the linear address. In protected mode, the segment selector might indicate a segment descriptor from either the global descriptor table or a local descriptor table. Both cases are considered in this function. This function is a prerequisite for functions in subsequent commits that will obtain the aforementioned attributes of the segment descriptor. Improvements-by: Borislav Petkov <bp@suse.de> Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: ricardo.neri@intel.com Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Huang Rui <ray.huang@amd.com> Cc: Qiaowei Ren <qiaowei.ren@intel.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Kees Cook <keescook@chromium.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: "Ravi V. Shankar" <ravi.v.shankar@intel.com> Cc: Chris Metcalf <cmetcalf@mellanox.com> Cc: Brian Gerst <brgerst@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Colin Ian King <colin.king@canonical.com> Cc: Chen Yucong <slaoub@gmail.com> Cc: Adam Buchbinder <adam.buchbinder@gmail.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Lorenzo Stoakes <lstoakes@gmail.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Thomas Garnier <thgarnie@google.com> Link: https://lkml.kernel.org/r/1509135945-13762-15-git-send-email-ricardo.neri-calderon@linux.intel.com
This commit is contained in:
parent
32d0b95300
commit
670f928ba0
|
@ -6,9 +6,13 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/mmu_context.h>
|
||||
#include <asm/desc_defs.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/inat.h>
|
||||
#include <asm/insn.h>
|
||||
#include <asm/insn-eval.h>
|
||||
#include <asm/ldt.h>
|
||||
#include <asm/vm86.h>
|
||||
|
||||
#undef pr_fmt
|
||||
|
@ -468,6 +472,59 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
|
|||
return regoff[regno];
|
||||
}
|
||||
|
||||
/**
|
||||
* get_desc() - Obtain pointer to a segment descriptor
|
||||
* @sel: Segment selector
|
||||
*
|
||||
* Given a segment selector, obtain a pointer to the segment descriptor.
|
||||
* Both global and local descriptor tables are supported.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Pointer to segment descriptor on success.
|
||||
*
|
||||
* NULL on error.
|
||||
*/
|
||||
static struct desc_struct *get_desc(unsigned short sel)
|
||||
{
|
||||
struct desc_ptr gdt_desc = {0, 0};
|
||||
unsigned long desc_base;
|
||||
|
||||
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
||||
if ((sel & SEGMENT_TI_MASK) == SEGMENT_LDT) {
|
||||
struct desc_struct *desc = NULL;
|
||||
struct ldt_struct *ldt;
|
||||
|
||||
/* Bits [15:3] contain the index of the desired entry. */
|
||||
sel >>= 3;
|
||||
|
||||
mutex_lock(¤t->active_mm->context.lock);
|
||||
ldt = current->active_mm->context.ldt;
|
||||
if (ldt && sel < ldt->nr_entries)
|
||||
desc = &ldt->entries[sel];
|
||||
|
||||
mutex_unlock(¤t->active_mm->context.lock);
|
||||
|
||||
return desc;
|
||||
}
|
||||
#endif
|
||||
native_store_gdt(&gdt_desc);
|
||||
|
||||
/*
|
||||
* Segment descriptors have a size of 8 bytes. Thus, the index is
|
||||
* multiplied by 8 to obtain the memory offset of the desired descriptor
|
||||
* from the base of the GDT. As bits [15:3] of the segment selector
|
||||
* contain the index, it can be regarded as multiplied by 8 already.
|
||||
* All that remains is to clear bits [2:0].
|
||||
*/
|
||||
desc_base = sel & ~(SEGMENT_RPL_MASK | SEGMENT_TI_MASK);
|
||||
|
||||
if (desc_base > gdt_desc.size)
|
||||
return NULL;
|
||||
|
||||
return (struct desc_struct *)(gdt_desc.address + desc_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* insn_get_modrm_rm_off() - Obtain register in r/m part of the ModRM byte
|
||||
* @insn: Instruction containing the ModRM byte
|
||||
|
|
Loading…
Reference in New Issue