lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 22 Jul 2021 13:57:16 -0700
From:   Yu-cheng Yu <yu-cheng.yu@...el.com>
To:     x86@...nel.org, "H. Peter Anvin" <hpa@...or.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Ingo Molnar <mingo@...hat.com>, linux-kernel@...r.kernel.org,
        linux-doc@...r.kernel.org, linux-mm@...ck.org,
        linux-arch@...r.kernel.org, linux-api@...r.kernel.org,
        Arnd Bergmann <arnd@...db.de>,
        Andy Lutomirski <luto@...nel.org>,
        Balbir Singh <bsingharora@...il.com>,
        Borislav Petkov <bp@...en8.de>,
        Cyrill Gorcunov <gorcunov@...il.com>,
        Dave Hansen <dave.hansen@...ux.intel.com>,
        Eugene Syromiatnikov <esyr@...hat.com>,
        Florian Weimer <fweimer@...hat.com>,
        "H.J. Lu" <hjl.tools@...il.com>, Jann Horn <jannh@...gle.com>,
        Jonathan Corbet <corbet@....net>,
        Kees Cook <keescook@...omium.org>,
        Mike Kravetz <mike.kravetz@...cle.com>,
        Nadav Amit <nadav.amit@...il.com>,
        Oleg Nesterov <oleg@...hat.com>, Pavel Machek <pavel@....cz>,
        Peter Zijlstra <peterz@...radead.org>,
        Randy Dunlap <rdunlap@...radead.org>,
        "Ravi V. Shankar" <ravi.v.shankar@...el.com>,
        Dave Martin <Dave.Martin@....com>,
        Weijiang Yang <weijiang.yang@...el.com>,
        Pengfei Xu <pengfei.xu@...el.com>,
        Haitao Huang <haitao.huang@...el.com>,
        Rick P Edgecombe <rick.p.edgecombe@...el.com>
Cc:     Yu-cheng Yu <yu-cheng.yu@...el.com>
Subject: [PATCH v28 03/10] x86/cet/ibt: Handle signals for Indirect Branch Tracking

IBT state machine tracks CALL/JMP instructions.  When a such instruction is
executed and before arriving at an ENDBR, it is in WAIT_FOR_ENDBR state,
which can be read from CET_WAIT_ENDBR bit of MSR_IA32_U_CET.

Further details are described in Intel SDM Vol. 1, Sec. 18.3.

In handling signals, WAIT_FOR_ENDBR state is saved/restored with a new
UC_WAIT_ENDBR flag being introduced.

A legacy IA32 signal frame does not have ucontext, and cannot be supported
with a uc flag.  Thus, IBT feature is not supported for ia32 app's, which
is handled in a separate patch.

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@...el.com>
Cc: Andy Lutomirski <luto@...nel.org>
Cc: Cyrill Gorcunov <gorcunov@...il.com>
Cc: Florian Weimer <fweimer@...hat.com>
Cc: H. Peter Anvin <hpa@...or.com>
Cc: Kees Cook <keescook@...omium.org>
Link: https://lore.kernel.org/linux-api/f6e61dae-9805-c855-8873-7481ceb7ea79@intel.com/
---
 arch/x86/ia32/ia32_signal.c          | 15 ++++++++--
 arch/x86/include/asm/cet.h           |  4 +++
 arch/x86/include/uapi/asm/ucontext.h |  5 ++++
 arch/x86/kernel/ibt.c                | 41 ++++++++++++++++++++++++++++
 arch/x86/kernel/signal.c             |  6 ++++
 5 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index d7a30bc98e66..77d0fa90cc19 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -129,6 +129,7 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
 {
 	struct pt_regs *regs = current_pt_regs();
 	struct rt_sigframe_ia32 __user *frame;
+	unsigned int uc_flags;
 	sigset_t set;
 
 	frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
@@ -137,6 +138,11 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
 		goto badframe;
 	if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask))
 		goto badframe;
+	if (__get_user(uc_flags, &frame->uc.uc_flags))
+		goto badframe;
+
+	if (uc_flags & UC_WAIT_ENDBR)
+		ibt_set_wait_endbr();
 
 	set_current_blocked(&set);
 
@@ -312,6 +318,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
 			compat_sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe_ia32 __user *frame;
+	unsigned int uc_flags = 0;
 	void __user *restorer;
 	void __user *fp = NULL;
 
@@ -339,6 +346,9 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
 	if (setup_signal_shadow_stack(1, restorer))
 		return -EFAULT;
 
+	if (ibt_get_clear_wait_endbr())
+		uc_flags |= UC_WAIT_ENDBR;
+
 	if (!user_access_begin(frame, sizeof(*frame)))
 		return -EFAULT;
 
@@ -348,9 +358,8 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
 
 	/* Create the ucontext.  */
 	if (static_cpu_has(X86_FEATURE_XSAVE))
-		unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
-	else
-		unsafe_put_user(0, &frame->uc.uc_flags, Efault);
+		uc_flags |= UC_FP_XSTATE;
+	unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
 	unsafe_put_user(0, &frame->uc.uc_link, Efault);
 	unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
 
diff --git a/arch/x86/include/asm/cet.h b/arch/x86/include/asm/cet.h
index 3dfca29a7c0b..2618faf3fda5 100644
--- a/arch/x86/include/asm/cet.h
+++ b/arch/x86/include/asm/cet.h
@@ -46,9 +46,13 @@ static inline int restore_signal_shadow_stack(void) { return 0; }
 #ifdef CONFIG_X86_IBT
 int ibt_setup(void);
 void ibt_disable(void);
+int ibt_get_clear_wait_endbr(void);
+int ibt_set_wait_endbr(void);
 #else
 static inline int ibt_setup(void) { return 0; }
 static inline void ibt_disable(void) {}
+static inline int ibt_get_clear_wait_endbr(void) { return 0; }
+static inline int ibt_set_wait_endbr(void) { return 0; }
 #endif
 
 #ifdef CONFIG_X86_SHADOW_STACK
diff --git a/arch/x86/include/uapi/asm/ucontext.h b/arch/x86/include/uapi/asm/ucontext.h
index 5657b7a49f03..905419de2cc7 100644
--- a/arch/x86/include/uapi/asm/ucontext.h
+++ b/arch/x86/include/uapi/asm/ucontext.h
@@ -51,6 +51,11 @@
 #define UC_STRICT_RESTORE_SS	0x4
 #endif
 
+/*
+ * Indicates IBT WAIT-ENDBR status.
+ */
+#define UC_WAIT_ENDBR		0x08
+
 #include <asm-generic/ucontext.h>
 
 #endif /* _ASM_X86_UCONTEXT_H */
diff --git a/arch/x86/kernel/ibt.c b/arch/x86/kernel/ibt.c
index 4ab7af33b274..5ab8632a1f7e 100644
--- a/arch/x86/kernel/ibt.c
+++ b/arch/x86/kernel/ibt.c
@@ -56,3 +56,44 @@ void ibt_disable(void)
 	ibt_set_clear_msr_bits(0, CET_ENDBR_EN);
 	current->thread.shstk.ibt = 0;
 }
+
+int ibt_get_clear_wait_endbr(void)
+{
+	u64 msr_val = 0;
+
+	if (!current->thread.shstk.ibt)
+		return 0;
+
+	fpregs_lock();
+
+	if (!test_thread_flag(TIF_NEED_FPU_LOAD)) {
+		if (!rdmsrl_safe(MSR_IA32_U_CET, &msr_val))
+			wrmsrl(MSR_IA32_U_CET, msr_val & ~CET_WAIT_ENDBR);
+	} else {
+		struct cet_user_state *cet;
+
+		/*
+		 * If !TIF_NEED_FPU_LOAD and get_xsave_addr() returns zero,
+		 * XFEATURE_CET_USER is in init state (cet is not active).
+		 * Return zero status.
+		 */
+		cet = get_xsave_addr(&current->thread.fpu.state.xsave,
+				     XFEATURE_CET_USER);
+		if (cet) {
+			msr_val = cet->user_cet;
+			cet->user_cet = msr_val & ~CET_WAIT_ENDBR;
+		}
+	}
+
+	fpregs_unlock();
+
+	return msr_val & CET_WAIT_ENDBR;
+}
+
+int ibt_set_wait_endbr(void)
+{
+	if (!current->thread.shstk.ibt)
+		return 0;
+
+	return ibt_set_clear_msr_bits(CET_WAIT_ENDBR, 0);
+}
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 661e46803b84..a1285650852e 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -135,6 +135,9 @@ static int restore_sigcontext(struct pt_regs *regs,
 	 */
 	if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
 		force_valid_ss(regs);
+
+	if (uc_flags & UC_WAIT_ENDBR)
+		ibt_set_wait_endbr();
 #endif
 
 	return fpu__restore_sig((void __user *)sc.fpstate,
@@ -455,6 +458,9 @@ static unsigned long frame_uc_flags(struct pt_regs *regs)
 	if (likely(user_64bit_mode(regs)))
 		flags |= UC_STRICT_RESTORE_SS;
 
+	if (ibt_get_clear_wait_endbr())
+		flags |= UC_WAIT_ENDBR;
+
 	return flags;
 }
 
-- 
2.21.0

Powered by blists - more mailing lists