public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Yian Chen <yian.chen@intel.com>
To: linux-kernel@vger.kernel.org, x86@kernel.org,
	Andy Lutomirski <luto@kernel.org>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Ravi Shankar <ravi.v.shankar@intel.com>,
	Tony Luck <tony.luck@intel.com>,
	Sohil Mehta <sohil.mehta@intel.com>,
	Paul Lai <paul.c.lai@intel.com>, Yian Chen <yian.chen@intel.com>
Subject: [PATCH 3/7] x86/cpu: Disable kernel LASS when patching kernel alternatives
Date: Mon,  9 Jan 2023 21:52:00 -0800	[thread overview]
Message-ID: <20230110055204.3227669-4-yian.chen@intel.com> (raw)
In-Reply-To: <20230110055204.3227669-1-yian.chen@intel.com>

Most of the kernel is mapped at virtual addresses
in the upper half of the address range. But kernel
deliberately initialized a temporary mm area
within the lower half of the address range
for text poking, see commit 4fc19708b165
("x86/alternatives: Initialize temporary mm
for patching").

LASS stops access to a lower half address in kernel,
and this can be deactivated if AC bit in EFLAGS
register is set. Hence use stac and clac instructions
around access to the address to avoid triggering a
LASS #GP fault.

Kernel objtool validation warns if the binary calls
to a non-whitelisted function that exists outside of
the stac/clac guard, or references any function with a
dynamic function pointer inside the guard; see section
9 in the document tools/objtool/Documentation/objtool.txt.

For these reasons, also considering text poking size is
usually small, simple modifications have been done
in function text_poke_memcpy() and text_poke_memset() to
avoid non-whitelisted function calls inside the stac/clac
guard.

Gcc may detect and replace the target with its built-in
functions. However, the replacement would break the
objtool validation criteria. Hence, add compiler option
-fno-builtin for the file.

Co-developed-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Yian Chen <yian.chen@intel.com>
---
 arch/x86/include/asm/smap.h      | 13 +++++++++++++
 arch/x86/kernel/Makefile         |  2 ++
 arch/x86/kernel/alternative.c    | 21 +++++++++++++++++++--
 tools/objtool/arch/x86/special.c |  2 ++
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
index bab490379c65..6f7ac0839b10 100644
--- a/arch/x86/include/asm/smap.h
+++ b/arch/x86/include/asm/smap.h
@@ -39,6 +39,19 @@ static __always_inline void stac(void)
 	alternative("", __ASM_STAC, X86_FEATURE_SMAP);
 }
 
+/* Deactivate/activate LASS via AC bit in EFLAGS register */
+static __always_inline void low_addr_access_begin(void)
+{
+	/* Note: a barrier is implicit in alternative() */
+	alternative("", __ASM_STAC, X86_FEATURE_LASS);
+}
+
+static __always_inline void low_addr_access_end(void)
+{
+	/* Note: a barrier is implicit in alternative() */
+	alternative("", __ASM_CLAC, X86_FEATURE_LASS);
+}
+
 static __always_inline unsigned long smap_save(void)
 {
 	unsigned long flags;
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 96d51bbc2bd4..f8a455fc56a2 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -7,6 +7,8 @@ extra-y	+= vmlinux.lds
 
 CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 
+CFLAGS_alternative.o	+= -fno-builtin
+
 ifdef CONFIG_FUNCTION_TRACER
 # Do not profile debug and lowlevel utilities
 CFLAGS_REMOVE_tsc.o = -pg
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 7d8c3cbde368..4de8b54fb5f2 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -1530,14 +1530,31 @@ __ro_after_init unsigned long poking_addr;
 
 static void text_poke_memcpy(void *dst, const void *src, size_t len)
 {
-	memcpy(dst, src, len);
+	const char *s = src;
+	char *d = dst;
+
+	/* The parameter dst ends up referencing to the global variable
+	 * poking_addr, which is mapped to the low half address space.
+	 * In kernel, accessing the low half address range is prevented
+	 * by LASS. So relax LASS prevention while accessing the memory
+	 * range.
+	 */
+	low_addr_access_begin();
+	while (len-- > 0)
+		*d++ = *s++;
+	low_addr_access_end();
 }
 
 static void text_poke_memset(void *dst, const void *src, size_t len)
 {
 	int c = *(const int *)src;
+	char *d = dst;
 
-	memset(dst, c, len);
+	/* The same comment as it is in function text_poke_memcpy */
+	low_addr_access_begin();
+	while (len-- > 0)
+		*d++ = c;
+	low_addr_access_end();
 }
 
 typedef void text_poke_f(void *dst, const void *src, size_t len);
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 7c97b7391279..3a34ebe3966a 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -6,11 +6,13 @@
 
 #define X86_FEATURE_POPCNT (4 * 32 + 23)
 #define X86_FEATURE_SMAP   (9 * 32 + 20)
+#define X86_FEATURE_LASS   (12 * 32 + 6)
 
 void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
 {
 	switch (feature) {
 	case X86_FEATURE_SMAP:
+	case X86_FEATURE_LASS:
 		/*
 		 * If UACCESS validation is enabled; force that alternative;
 		 * otherwise force it the other way.
-- 
2.34.1


  parent reply	other threads:[~2023-01-10  5:57 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-10  5:51 [PATCH 0/7] Enable LASS (Linear Address space Separation) Yian Chen
2023-01-10  5:51 ` [PATCH 1/7] x86/cpu: Enumerate LASS CPUID and CR4 bits Yian Chen
2023-01-10 20:14   ` Sohil Mehta
2023-01-11  0:13     ` Dave Hansen
2023-01-11 23:23       ` Chen, Yian
2023-01-12  0:06         ` Luck, Tony
2023-01-12  0:15           ` Chen, Yian
2023-01-11 19:21     ` Chen, Yian
2023-01-10  5:51 ` [PATCH 2/7] x86: Add CONFIG option X86_LASS Yian Chen
2023-01-10 21:05   ` Sohil Mehta
2023-01-12  0:13     ` Chen, Yian
2023-01-10  5:52 ` Yian Chen [this message]
2023-01-10 21:04   ` [PATCH 3/7] x86/cpu: Disable kernel LASS when patching kernel alternatives Peter Zijlstra
2023-01-11  1:01     ` Chen, Yian
2023-01-11  9:10       ` Peter Zijlstra
2023-01-10 22:41   ` Sohil Mehta
2023-01-12  0:27     ` Chen, Yian
2023-01-12  0:37       ` Dave Hansen
2023-01-12 18:36         ` Chen, Yian
2023-01-12 18:48           ` Dave Hansen
2023-02-01  2:25             ` Sohil Mehta
2023-02-01 18:20               ` Dave Hansen
2023-02-01  2:10         ` Sohil Mehta
2023-01-10  5:52 ` [PATCH 4/7] x86/vsyscall: Setup vsyscall to compromise LASS protection Yian Chen
2023-01-11  0:34   ` Sohil Mehta
2023-01-12  1:43     ` Chen, Yian
2023-01-12  2:49       ` Sohil Mehta
2023-01-21  4:09   ` Andy Lutomirski
2023-01-10  5:52 ` [PATCH 5/7] x86/cpu: Enable LASS (Linear Address Space Separation) Yian Chen
2023-01-11 22:22   ` Sohil Mehta
2023-01-12 17:56     ` Chen, Yian
2023-01-12 18:17   ` Dave Hansen
2023-01-13  1:17     ` Sohil Mehta
2023-01-13 19:39       ` Sohil Mehta
2023-01-10  5:52 ` [PATCH 6/7] x86/cpu: Set LASS as pinning sensitive CR4 bit Yian Chen
2023-01-10  5:52 ` [PATCH 7/7] x86/kvm: Expose LASS feature to VM guest Yian Chen
2023-02-07  3:21   ` Wang, Lei
2023-02-09 17:18     ` Sean Christopherson
2023-01-10 19:48 ` [PATCH 0/7] Enable LASS (Linear Address space Separation) Sohil Mehta
2023-01-10 22:57 ` Dave Hansen

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=20230110055204.3227669-4-yian.chen@intel.com \
    --to=yian.chen@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=paul.c.lai@intel.com \
    --cc=ravi.v.shankar@intel.com \
    --cc=sohil.mehta@intel.com \
    --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