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 ---