mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
To: Ingo Molnar <mingo@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H. Peter Anvin" <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>, Andy Lutomirski <luto@kernel.org>,
	Tony Luck <tony.luck@intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	"Ravi V. Shankar" <ravi.v.shankar@intel.com>,
	x86@kernel.org, ricardo.neri@intel.com,
	linux-kernel@vger.kernel.org,
	Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Subject: [RESEND PATCH v2 4/4] x86/umip: Warn if UMIP-protected instructions are used
Date: Mon, 13 Nov 2017 22:29:45 -0800	[thread overview]
Message-ID: <1510640985-18412-5-git-send-email-ricardo.neri-calderon@linux.intel.com> (raw)
In-Reply-To: <1510640985-18412-1-git-send-email-ricardo.neri-calderon@linux.intel.com>

Issue a rate-limited warning whenever any of the instructions that UMIP
protects (i.e., SGDT, SIDT, SLDT, STR and SMSW) are used by user space
programs.

This is useful because, with UMIP enabled, the few programs that use such
instructions will start receiving a SIGSEGV signal. In the specific cases
for which emulation is provided (instructions SGDT, SIDT and SMSW in
protected and virtual-8086 modes), a warning is also helpful to encourage
updates in such programs to avoid the use of such instructions.

An existing rate-limited pr_err() is converted to use the new function
umip_pr_warn() in order to have it printing at the same rate and log
level.

Cc: Andy Lutomirski <luto@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: x86@kernel.org
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
---
 arch/x86/kernel/umip.c | 65 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/umip.c b/arch/x86/kernel/umip.c
index 2e09b5b..50f4b11 100644
--- a/arch/x86/kernel/umip.c
+++ b/arch/x86/kernel/umip.c
@@ -82,6 +82,54 @@
 #define	UMIP_INST_SLDT  3       /* 0F 00 /0 */
 #define	UMIP_INST_STR   4       /* 0F 00 /1 */
 
+const char * const umip_insns[5] = {
+	[UMIP_INST_SGDT] = "sgdt",
+	[UMIP_INST_SIDT] = "sidt",
+	[UMIP_INST_SMSW] = "smsw",
+	[UMIP_INST_SLDT] = "sldt",
+	[UMIP_INST_STR] = "str",
+};
+
+/*
+ * If you change these strings, ensure that buffers using them are sufficiently
+ * large.
+ */
+static const char umip_warn_use[] = "cannot be used by applications.";
+static const char umip_warn_emu[] = "For now, expensive software emulation returns result.";
+
+/**
+ * umip_pr_warn() - Print a rate-limited warning
+ * @regs:	Register set with the context in which the warning is printed
+ * @msg:	Pointer to a string with the warning message
+ * @error:	Error code to print along with the warning
+ *
+ * Print the message contained in @msg along with the task name, ID number and
+ * instruction and stack pointers of the associated process. Optionally, an
+ * error code is printed if @error is not zero. These warning messages are
+ * limited to a burst of 5 messages every two minutes.
+ *
+ * Returns:
+ *
+ * None.
+ */
+static void umip_pr_warn(struct pt_regs *regs, char *msg, long error)
+{
+	struct task_struct *tsk = current;
+	char err_str[8 + BITS_PER_LONG / 4] = "";
+
+	/* Bursts of 5 messages every two minutes */
+	static DEFINE_RATELIMIT_STATE(ratelimit, 2 * 60 * HZ, 5);
+
+	if (!__ratelimit(&ratelimit))
+		return;
+
+	if (error)
+		snprintf(err_str, sizeof(err_str), " error:%lx", error);
+
+	pr_warn("%s[%d] %s ip:%lx sp:%lx%s\n", tsk->comm, task_pid_nr(tsk), msg,
+		regs->ip, regs->sp, err_str);
+}
+
 /**
  * identify_insn() - Identify a UMIP-protected instruction
  * @insn:	Instruction structure with opcode and ModRM byte.
@@ -236,10 +284,7 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
 	if (!(show_unhandled_signals && unhandled_signal(tsk, SIGSEGV)))
 		return;
 
-	pr_err_ratelimited("%s[%d] umip emulation segfault ip:%lx sp:%lx error:%x in %lx\n",
-			   tsk->comm, task_pid_nr(tsk), regs->ip,
-			   regs->sp, X86_PF_USER | X86_PF_WRITE,
-			   regs->ip);
+	umip_pr_warn(regs, "segfault at", X86_PF_USER | X86_PF_WRITE);
 }
 
 /**
@@ -264,10 +309,10 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
 bool fixup_umip_exception(struct pt_regs *regs)
 {
 	int not_copied, nr_copied, reg_offset, dummy_data_size, umip_inst;
+	unsigned char buf[MAX_INSN_SIZE], warn[128];
 	unsigned long seg_base = 0, *reg_addr;
 	/* 10 bytes is the maximum size of the result of UMIP instructions */
 	unsigned char dummy_data[10] = { 0 };
-	unsigned char buf[MAX_INSN_SIZE];
 	void __user *uaddr;
 	struct insn insn;
 	char seg_defs;
@@ -326,10 +371,18 @@ bool fixup_umip_exception(struct pt_regs *regs)
 	if (umip_inst < 0)
 		return false;
 
+	snprintf(warn, sizeof(warn), "%s %s", umip_insns[umip_inst],
+		 umip_warn_use);
+
 	/* Do not emulate SLDT, STR or user long mode processes. */
 	if (umip_inst == UMIP_INST_STR || umip_inst == UMIP_INST_SLDT ||
-	    user_64bit_mode(regs))
+	    user_64bit_mode(regs)) {
+		umip_pr_warn(regs, warn, 0);
 		return false;
+	}
+
+	snprintf(warn, sizeof(warn), "%s %s", warn, umip_warn_emu);
+	umip_pr_warn(regs, warn, 0);
 
 	if (emulate_umip_insn(&insn, umip_inst, dummy_data, &dummy_data_size))
 		return false;
-- 
2.7.4

  parent reply	other threads:[~2017-11-14  6:31 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-14  6:29 [RESEND PATCH v2 0/4] x86: Tweaks for UMIP Ricardo Neri
2017-11-14  6:29 ` [RESEND PATCH v2 1/4] x86/umip: Select X86_INTEL_UMIP by default Ricardo Neri
2017-11-14  9:30   ` [tip:x86/urgent] " tip-bot for Ricardo Neri
2017-11-14  6:29 ` [RESEND PATCH v2 2/4] x86/umip: Inform that UMIP has been enabled Ricardo Neri
2017-11-14  9:31   ` [tip:x86/urgent] x86/umip: Print a line in the boot log " tip-bot for Ricardo Neri
2017-11-14  6:29 ` [RESEND PATCH v2 3/4] x86/umip: Identify the str and sldt instructions Ricardo Neri
2017-11-14  7:21   ` Ingo Molnar
2017-11-15  2:44     ` Ricardo Neri
2017-11-14  9:31   ` [tip:x86/urgent] x86/umip: Identify the STR and SLDT instructions tip-bot for Ricardo Neri
2017-11-14  6:29 ` Ricardo Neri [this message]
2017-11-14  7:34   ` [RESEND PATCH v2 4/4] x86/umip: Warn if UMIP-protected instructions are used Ingo Molnar
2017-11-15  2:56     ` Ricardo Neri
2017-11-15  8:41       ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1510640985-18412-5-git-send-email-ricardo.neri-calderon@linux.intel.com \
    --to=ricardo.neri-calderon@linux.intel.com \
    --cc=bp@suse.de \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=ravi.v.shankar@intel.com \
    --cc=ricardo.neri@intel.com \
    --cc=tglx@linutronix.de \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®