Commit 670f928b authored by Ricardo Neri's avatar Ricardo Neri Committed by Thomas Gleixner

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: default avatarBorislav Petkov <bp@suse.de>
Signed-off-by: default avatarRicardo Neri <ricardo.neri-calderon@linux.intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarBorislav 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
parent 32d0b953
...@@ -6,9 +6,13 @@ ...@@ -6,9 +6,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/ratelimit.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/inat.h>
#include <asm/insn.h> #include <asm/insn.h>
#include <asm/insn-eval.h> #include <asm/insn-eval.h>
#include <asm/ldt.h>
#include <asm/vm86.h> #include <asm/vm86.h>
#undef pr_fmt #undef pr_fmt
...@@ -468,6 +472,59 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs, ...@@ -468,6 +472,59 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
return regoff[regno]; 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(&current->active_mm->context.lock);
ldt = current->active_mm->context.ldt;
if (ldt && sel < ldt->nr_entries)
desc = &ldt->entries[sel];
mutex_unlock(&current->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_get_modrm_rm_off() - Obtain register in r/m part of the ModRM byte
* @insn: Instruction containing the ModRM byte * @insn: Instruction containing the ModRM byte
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment