Lines Matching +full:global +full:- +full:regs

2  * umip.c Emulation for instruction protected by the User-Mode Instruction
6 * Ricardo Neri <ricardo.neri-[email protected]>
13 #include <asm/insn-eval.h>
19 /** DOC: Emulation for User-Mode Instruction Prevention (UMIP)
21 * User-Mode Instruction Prevention is a security feature present in recent
27 * the UMIP-protected instructions (in the form of a SIGSEGV signal), it can be
31 * global descriptor and interrupt descriptor tables, the segment selectors of
44 * not the actual location of the table. The result is emulated as a hard-coded
52 * - SLDT returns (GDT_ENTRY_LDT * 8) if an LDT has been set, 0 if not.
53 * - STR returns (GDT_ENTRY_TSS * 8).
55 * Emulation is provided for both 32-bit and 64-bit processes.
69 * The SGDT and SIDT instructions store the contents of the global descriptor
72 * the table and 2 bytes are used to store the limit. In 32-bit processes X
73 * has a value of 4, in 64-bit processes X has a value of 8.
93 #define umip_pr_err(regs, fmt, ...) \ argument
94 umip_printk(regs, KERN_ERR, fmt, ##__VA_ARGS__)
95 #define umip_pr_debug(regs, fmt, ...) \ argument
96 umip_printk(regs, KERN_DEBUG, fmt, ##__VA_ARGS__)
99 * umip_printk() - Print a rate-limited message
100 * @regs: Register set with the context in which the warning is printed
107 * UMIP-protected instructions. Thus, the printed text is prepended with the
109 * instruction and stack pointers in @regs as seen when entering kernel mode.
116 void umip_printk(const struct pt_regs *regs, const char *log_level, in umip_printk() argument
131 printk("%s" pr_fmt("%s[%d] ip:%lx sp:%lx: %pV"), log_level, tsk->comm, in umip_printk()
132 task_pid_nr(tsk), regs->ip, regs->sp, &vaf); in umip_printk()
137 * identify_insn() - Identify a UMIP-protected instruction
140 * From the opcode and ModRM.reg in @insn identify, if any, a UMIP-protected
145 * On success, a constant identifying a specific UMIP-protected instruction that
148 * -EINVAL on error or when not an UMIP-protected instruction that can be
156 if (!insn->modrm.nbytes) in identify_insn()
157 return -EINVAL; in identify_insn()
160 if (insn->opcode.bytes[0] != 0xf) in identify_insn()
161 return -EINVAL; in identify_insn()
163 if (insn->opcode.bytes[1] == 0x1) { in identify_insn()
164 switch (X86_MODRM_REG(insn->modrm.value)) { in identify_insn()
172 return -EINVAL; in identify_insn()
174 } else if (insn->opcode.bytes[1] == 0x0) { in identify_insn()
175 if (X86_MODRM_REG(insn->modrm.value) == 0) in identify_insn()
177 else if (X86_MODRM_REG(insn->modrm.value) == 1) in identify_insn()
180 return -EINVAL; in identify_insn()
182 return -EINVAL; in identify_insn()
187 * emulate_umip_insn() - Emulate UMIP instructions and return dummy values
192 * @x86_64: true if process is 64-bit, false otherwise
203 * 0 on success, -EINVAL on error while emulating.
209 return -EINVAL; in emulate_umip_insn()
212 * global and interrupt descriptor table, respectively. According to the in emulate_umip_insn()
213 * Intel Software Development manual, the base address can be 24-bit, in emulate_umip_insn()
214 * 32-bit or 64-bit. Limit is always 16-bit. If the operand size is in emulate_umip_insn()
215 * 16-bit, the returned value of the base address is supposed to be a in emulate_umip_insn()
216 * zero-extended 24-byte number. However, it seems that a 32-byte number in emulate_umip_insn()
224 if (X86_MODRM_MOD(insn->modrm.value) == 3) in emulate_umip_insn()
225 return -EINVAL; in emulate_umip_insn()
233 * 64-bit processes use the entire dummy base address. in emulate_umip_insn()
234 * 32-bit processes use the lower 32 bits of the base address. in emulate_umip_insn()
258 down_read(&current->mm->context.ldt_usr_sem); in emulate_umip_insn()
259 if (current->mm->context.ldt) in emulate_umip_insn()
263 up_read(&current->mm->context.ldt_usr_sem); in emulate_umip_insn()
277 if (X86_MODRM_MOD(insn->modrm.value) == 3) in emulate_umip_insn()
278 *data_size = insn->opnd_bytes; in emulate_umip_insn()
284 return -EINVAL; in emulate_umip_insn()
291 * force_sig_info_umip_fault() - Force a SIGSEGV with SEGV_MAPERR
293 * @regs: Register set containing the instruction pointer
301 static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs) in force_sig_info_umip_fault() argument
305 tsk->thread.cr2 = (unsigned long)addr; in force_sig_info_umip_fault()
306 tsk->thread.error_code = X86_PF_USER | X86_PF_WRITE; in force_sig_info_umip_fault()
307 tsk->thread.trap_nr = X86_TRAP_PF; in force_sig_info_umip_fault()
314 umip_pr_err(regs, "segfault in emulation. error%x\n", in force_sig_info_umip_fault()
319 * fixup_umip_exception() - Fixup a general protection fault caused by UMIP
320 * @regs: Registers as saved when entering the #GP handler
327 * If operands are memory addresses, results are copied to user-space memory as
336 bool fixup_umip_exception(struct pt_regs *regs) in fixup_umip_exception() argument
346 if (!regs) in fixup_umip_exception()
353 nr_copied = insn_fetch_from_user(regs, buf); in fixup_umip_exception()
357 if (!insn_decode_from_regs(&insn, regs, buf, nr_copied)) in fixup_umip_exception()
364 umip_pr_debug(regs, "%s instruction cannot be used by applications.\n", in fixup_umip_exception()
367 umip_pr_debug(regs, "For now, expensive software emulation returns the result.\n"); in fixup_umip_exception()
370 user_64bit_mode(regs))) in fixup_umip_exception()
380 reg_offset = insn_get_modrm_rm_off(&insn, regs); in fixup_umip_exception()
384 * the exception is -EDOM. Since we expect a register operand, in fixup_umip_exception()
390 reg_addr = (unsigned long *)((unsigned long)regs + reg_offset); in fixup_umip_exception()
393 uaddr = insn_get_addr_ref(&insn, regs); in fixup_umip_exception()
394 if ((unsigned long)uaddr == -1L) in fixup_umip_exception()
403 force_sig_info_umip_fault(uaddr, regs); in fixup_umip_exception()
409 regs->ip += insn.length; in fixup_umip_exception()