aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/umip.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 1f1f2d54dab5..dabbac30acdf 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -82,6 +82,57 @@
82#define UMIP_INST_SLDT 3 /* 0F 00 /0 */ 82#define UMIP_INST_SLDT 3 /* 0F 00 /0 */
83#define UMIP_INST_STR 4 /* 0F 00 /1 */ 83#define UMIP_INST_STR 4 /* 0F 00 /1 */
84 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
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
85/** 136/**
86 * identify_insn() - Identify a UMIP-protected instruction 137 * identify_insn() - Identify a UMIP-protected instruction
87 * @insn: Instruction structure with opcode and ModRM byte. 138 * @insn: Instruction structure with opcode and ModRM byte.
@@ -236,10 +287,8 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
236 if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV))) 287 if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV)))
237 return; 288 return;
238 289
239 pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n", 290 umip_pr_err(regs, "segfault in emulation. error%x\n",
240 tsk->comm, task_pid_nr(tsk), regs->ip, 291 X86_PF_USER | X86_PF_WRITE);
241 regs->sp, X86_PF_USER | X86_PF_WRITE,
242 regs->ip);
243} 292}
244 293
245/** 294/**
@@ -326,10 +375,15 @@ bool fixup_umip_exception(struct pt_regs *regs)
326 if (umip_inst < 0) 375 if (umip_inst < 0)
327 return false; 376 return false;
328 377
378 umip_pr_warning(regs, "%s instruction cannot be used by applications.\n",
379 umip_insns[umip_inst]);
380
329 /* Do not emulate SLDT, STR or user long mode processes. */ 381 /* Do not emulate SLDT, STR or user long mode processes. */
330 if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs)) 382 if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT || user_64bit_mode(regs))
331 return false; 383 return false;
332 384
385 umip_pr_warning(regs, "For now, expensive software emulation returns the result.\n");
386
333 if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size)) 387 if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
334 return false; 388 return false;
335 389