umip.c (d4bfeabe9ff7967f4b8c24aabf2de1ce3a909cd9) | umip.c (fd11a6496e12848d4eeb21029c2c288bbc638048) |
---|---|
1/* 2 * umip.c Emulation for instruction protected by the Intel User-Mode 3 * Instruction Prevention feature 4 * 5 * Copyright (c) 2017, Intel Corporation. 6 * Ricardo Neri <ricardo.neri-calderon@linux.intel.com> 7 */ 8 --- 64 unchanged lines hidden (view full) --- 73 * the table and 2 bytes are used to store the limit. In 32-bit processes, the 74 * only processes for which emulation is provided, X has a value of 4. 75 */ 76#define UMIP_GDT_IDT_BASE_SIZE 4 77#define UMIP_GDT_IDT_LIMIT_SIZE 2 78 79#define UMIP_INST_SGDT 0 /* 0F 01 /0 */ 80#define UMIP_INST_SIDT 1 /* 0F 01 /1 */ | 1/* 2 * umip.c Emulation for instruction protected by the Intel User-Mode 3 * Instruction Prevention feature 4 * 5 * Copyright (c) 2017, Intel Corporation. 6 * Ricardo Neri <ricardo.neri-calderon@linux.intel.com> 7 */ 8 --- 64 unchanged lines hidden (view full) --- 73 * the table and 2 bytes are used to store the limit. In 32-bit processes, the 74 * only processes for which emulation is provided, X has a value of 4. 75 */ 76#define UMIP_GDT_IDT_BASE_SIZE 4 77#define UMIP_GDT_IDT_LIMIT_SIZE 2 78 79#define UMIP_INST_SGDT 0 /* 0F 01 /0 */ 80#define UMIP_INST_SIDT 1 /* 0F 01 /1 */ |
81#define UMIP_INST_SMSW 3 /* 0F 01 /4 */ | 81#define UMIP_INST_SMSW 2 /* 0F 01 /4 */ 82#define UMIP_INST_SLDT 3 /* 0F 00 /0 */ 83#define UMIP_INST_STR 4 /* 0F 00 /1 */ |
82 | 84 |
85const char * const umip_insns[5] = { 86 [UMIP_INST_SGDT] = "SGDT", 87 [UMIP_INST_SIDT] = "SIDT", 88 [UMIP_INST_SMSW] = "SMSW", 89 [UMIP_INST_SLDT] = "SLDT", 90 [UMIP_INST_STR] = "STR", 91}; 92 93#define umip_pr_err(regs, fmt, ...) \ 94 umip_printk(regs, KERN_ERR, fmt, ##__VA_ARGS__) 95#define umip_pr_warning(regs, fmt, ...) \ 96 umip_printk(regs, KERN_WARNING, fmt, ##__VA_ARGS__) 97 |
|
83/** | 98/** |
99 * umip_printk() - Print a rate-limited message 100 * @regs: Register set with the context in which the warning is printed 101 * @log_level: Kernel log level to print the message 102 * @fmt: The text string to print 103 * 104 * Print the text contained in @fmt. The print rate is limited to bursts of 5 105 * messages every two minutes. The purpose of this customized version of 106 * printk() is to print messages when user space processes use any of the 107 * UMIP-protected instructions. Thus, the printed text is prepended with the 108 * task name and process ID number of the current task as well as the 109 * instruction and stack pointers in @regs as seen when entering kernel mode. 110 * 111 * Returns: 112 * 113 * None. 114 */ 115static __printf(3, 4) 116void umip_printk(const struct pt_regs *regs, const char *log_level, 117 const char *fmt, ...) 118{ 119 /* Bursts of 5 messages every two minutes */ 120 static DEFINE_RATELIMIT_STATE(ratelimit, 2 * 60 * HZ, 5); 121 struct task_struct *tsk = current; 122 struct va_format vaf; 123 va_list args; 124 125 if (!__ratelimit(&ratelimit)) 126 return; 127 128 va_start(args, fmt); 129 vaf.fmt = fmt; 130 vaf.va = &args; 131 printk("%s" pr_fmt("%s[%d] ip:%lx sp:%lx: %pV"), log_level, tsk->comm, 132 task_pid_nr(tsk), regs->ip, regs->sp, &vaf); 133 va_end(args); 134} 135 136/** |
|
84 * identify_insn() - Identify a UMIP-protected instruction 85 * @insn: Instruction structure with opcode and ModRM byte. 86 * 87 * From the opcode and ModRM.reg in @insn identify, if any, a UMIP-protected 88 * instruction that can be emulated. 89 * 90 * Returns: 91 * --- 21 unchanged lines hidden (view full) --- 113 return UMIP_INST_SGDT; 114 case 1: 115 return UMIP_INST_SIDT; 116 case 4: 117 return UMIP_INST_SMSW; 118 default: 119 return -EINVAL; 120 } | 137 * identify_insn() - Identify a UMIP-protected instruction 138 * @insn: Instruction structure with opcode and ModRM byte. 139 * 140 * From the opcode and ModRM.reg in @insn identify, if any, a UMIP-protected 141 * instruction that can be emulated. 142 * 143 * Returns: 144 * --- 21 unchanged lines hidden (view full) --- 166 return UMIP_INST_SGDT; 167 case 1: 168 return UMIP_INST_SIDT; 169 case 4: 170 return UMIP_INST_SMSW; 171 default: 172 return -EINVAL; 173 } |
174 } else if (insn->opcode.bytes[1] == 0x0) { 175 if (X86_MODRM_REG(insn->modrm.value) == 0) 176 return UMIP_INST_SLDT; 177 else if (X86_MODRM_REG(insn->modrm.value) == 1) 178 return UMIP_INST_STR; 179 else 180 return -EINVAL; 181 } else { 182 return -EINVAL; |
|
121 } | 183 } |
122 123 /* SLDT AND STR are not emulated */ 124 return -EINVAL; | |
125} 126 127/** 128 * emulate_umip_insn() - Emulate UMIP instructions and return dummy values 129 * @insn: Instruction structure with operands 130 * @umip_inst: A constant indicating the instruction to emulate 131 * @data: Buffer into which the dummy result is stored 132 * @data_size: Size of the emulated result --- 90 unchanged lines hidden (view full) --- 223 info.si_errno = 0; 224 info.si_code = SEGV_MAPERR; 225 info.si_addr = addr; 226 force_sig_info(SIGSEGV, &info, tsk); 227 228 if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) 229 return; 230 | 184} 185 186/** 187 * emulate_umip_insn() - Emulate UMIP instructions and return dummy values 188 * @insn: Instruction structure with operands 189 * @umip_inst: A constant indicating the instruction to emulate 190 * @data: Buffer into which the dummy result is stored 191 * @data_size: Size of the emulated result --- 90 unchanged lines hidden (view full) --- 282 info.si_errno = 0; 283 info.si_code = SEGV_MAPERR; 284 info.si_addr = addr; 285 force_sig_info(SIGSEGV, &info, tsk); 286 287 if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) 288 return; 289 |
231 pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n", 232 tsk->comm, task_pid_nr(tsk), regs->ip, 233 regs->sp, X86_PF_USER | X86_PF_WRITE, 234 regs->ip); | 290 umip_pr_err(regs, "segfault in emulation. error%x\n", 291 X86_PF_USER | X86_PF_WRITE); |
235} 236 237/** 238 * fixup_umip_exception() - Fixup a general protection fault caused by UMIP 239 * @regs: Registers as saved when entering the #GP handler 240 * 241 * The instructions sgdt, sidt, str, smsw, sldt cause a general protection 242 * fault if executed with CPL > 0 (i.e., from user space). If the offending --- 19 unchanged lines hidden (view full) --- 262 unsigned char buf[MAX_INSN_SIZE]; 263 void __user *uaddr; 264 struct insn insn; 265 char seg_defs; 266 267 if (!regs) 268 return false; 269 | 292} 293 294/** 295 * fixup_umip_exception() - Fixup a general protection fault caused by UMIP 296 * @regs: Registers as saved when entering the #GP handler 297 * 298 * The instructions sgdt, sidt, str, smsw, sldt cause a general protection 299 * fault if executed with CPL > 0 (i.e., from user space). If the offending --- 19 unchanged lines hidden (view full) --- 319 unsigned char buf[MAX_INSN_SIZE]; 320 void __user *uaddr; 321 struct insn insn; 322 char seg_defs; 323 324 if (!regs) 325 return false; 326 |
270 /* Do not emulate 64-bit processes. */ 271 if (user_64bit_mode(regs)) 272 return false; 273 | |
274 /* 275 * If not in user-space long mode, a custom code segment could be in 276 * use. This is true in protected mode (if the process defined a local 277 * descriptor table), or virtual-8086 mode. In most of the cases 278 * seg_base will be zero as in USER_CS. 279 */ 280 if (!user_64bit_mode(regs)) 281 seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS); --- 35 unchanged lines hidden (view full) --- 317 insn_get_length(&insn); 318 if (nr_copied < insn.length) 319 return false; 320 321 umip_inst = identify_insn(&insn); 322 if (umip_inst < 0) 323 return false; 324 | 327 /* 328 * If not in user-space long mode, a custom code segment could be in 329 * use. This is true in protected mode (if the process defined a local 330 * descriptor table), or virtual-8086 mode. In most of the cases 331 * seg_base will be zero as in USER_CS. 332 */ 333 if (!user_64bit_mode(regs)) 334 seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS); --- 35 unchanged lines hidden (view full) --- 370 insn_get_length(&insn); 371 if (nr_copied < insn.length) 372 return false; 373 374 umip_inst = identify_insn(&insn); 375 if (umip_inst < 0) 376 return false; 377 |
378 umip_pr_warning(regs, "%s instruction cannot be used by applications.\n", 379 umip_insns[umip_inst]); 380 381 /* Do not emulate SLDT, STR or user long mode processes. */ 382 if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs)) 383 return false; 384 385 umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n"); 386 |
|
325 if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) 326 return false; 327 328 /* 329 * If operand is a register, write result to the copy of the register 330 * value that was pushed to the stack when entering into kernel mode. 331 * Upon exit, the value we write will be restored to the actual hardware 332 * register. --- 34 unchanged lines hidden --- | 387 if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) 388 return false; 389 390 /* 391 * If operand is a register, write result to the copy of the register 392 * value that was pushed to the stack when entering into kernel mode. 393 * Upon exit, the value we write will be restored to the actual hardware 394 * register. --- 34 unchanged lines hidden --- |