• Ricardo Neri's avatar
    x86/umip: Add emulation code for UMIP instructions · 1e5db223
    Ricardo Neri authored
    The feature User-Mode Instruction Prevention present in recent Intel
    processor prevents a group of instructions (sgdt, sidt, sldt, smsw, and
    str) from being executed with CPL > 0. Otherwise, a general protection
    fault is issued.
    
    Rather than relaying to the user space the general protection fault caused
    by the UMIP-protected instructions (in the form of a SIGSEGV signal), it
    can be trapped and the instruction emulated to provide a dummy result.
    This allows to both conserve the current kernel behavior and not reveal the
    system resources that UMIP intends to protect (i.e., the locations of the
    global descriptor and interrupt descriptor tables, the segment selectors of
    the local descriptor table, the value of the task state register and the
    contents of the CR0 register).
    
    This emulation is needed because certain applications (e.g., WineHQ and
    DOSEMU2) rely on this subset of instructions to function. Given that sldt
    and str are not commonly used in programs that run on WineHQ or DOSEMU2,
    they are not emulated. Also, emulation is provided only for 32-bit
    processes; 64-bit processes that attempt to use the instructions that UMIP
    protects will receive the SIGSEGV signal issued as a consequence of the
    general protection fault.
    
    The instructions protected by UMIP can be split in two groups. Those which
    return a kernel memory address (sgdt and sidt) and those which return a
    value (smsw, sldt and str; the last two not emulated).
    
    For the instructions that return a kernel memory address, applications such
    as WineHQ rely on the result being located in the kernel memory space, not
    the actual location of the table. The result is emulated as a hard-coded
    value that lies close to the top of the kernel memory. The limit for the
    GDT and the IDT are set to zero.
    
    The instruction smsw is emulated to return the value that the register CR0
    has at boot time as set in the head_32.
    
    Care is taken to appropriately emulate the results when segmentation is
    used. That is, rather than relying on USER_DS and USER_CS, the function
    insn_get_addr_ref() inspects the segment descriptor pointed by the
    registers in pt_regs. This ensures that we correctly obtain the segment
    base address and the address and operand sizes even if the user space
    application uses a local descriptor table.
    Signed-off-by: default avatarRicardo Neri <ricardo.neri-calderon@linux.intel.com>
    Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Brian Gerst <brgerst@gmail.com>
    Cc: Chen Yucong <slaoub@gmail.com>
    Cc: Chris Metcalf <cmetcalf@mellanox.com>
    Cc: Dave Hansen <dave.hansen@linux.intel.com>
    Cc: Denys Vlasenko <dvlasenk@redhat.com>
    Cc: Fenghua Yu <fenghua.yu@intel.com>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Huang Rui <ray.huang@amd.com>
    Cc: Jiri Slaby <jslaby@suse.cz>
    Cc: Jonathan Corbet <corbet@lwn.net>
    Cc: Josh Poimboeuf <jpoimboe@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Masami Hiramatsu <mhiramat@kernel.org>
    Cc: Michael S. Tsirkin <mst@redhat.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
    Cc: Shuah Khan <shuah@kernel.org>
    Cc: Tony Luck <tony.luck@intel.com>
    Cc: Vlastimil Babka <vbabka@suse.cz>
    Cc: ricardo.neri@intel.com
    Link: http://lkml.kernel.org/r/1509935277-22138-8-git-send-email-ricardo.neri-calderon@linux.intel.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    1e5db223
umip.c 10.9 KB