From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
To: Dave Hansen <dave.hansen@linux.intel.com>,
Andy Lutomirski <luto@kernel.org>,
Peter Zijlstra <peterz@infradead.org>
Cc: x86@kernel.org, Kostya Serebryany <kcc@google.com>,
Andrey Ryabinin <ryabinin.a.a@gmail.com>,
Andrey Konovalov <andreyknvl@gmail.com>,
Alexander Potapenko <glider@google.com>,
Taras Madan <tarasmadan@google.com>,
Dmitry Vyukov <dvyukov@google.com>,
"H . J . Lu" <hjl.tools@gmail.com>,
Andi Kleen <ak@linux.intel.com>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
Bharata B Rao <bharata@amd.com>,
Jacob Pan <jacob.jun.pan@linux.intel.com>,
Ashok Raj <ashok.raj@intel.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Subject: [PATCHv13 05/16] x86/uaccess: Provide untagged_addr() and remove tags before address check
Date: Tue, 27 Dec 2022 06:08:18 +0300 [thread overview]
Message-ID: <20221227030829.12508-6-kirill.shutemov@linux.intel.com> (raw)
In-Reply-To: <20221227030829.12508-1-kirill.shutemov@linux.intel.com>
untagged_addr() is a helper used by the core-mm to strip tag bits and
get the address to the canonical shape. In only handles userspace
addresses. The untagging mask is stored in mmu_context and will be set
on enabling LAM for the process.
The tags must not be included into check whether it's okay to access the
userspace address.
Strip tags in access_ok().
get_user() and put_user() don't use access_ok(), but check access
against TASK_SIZE directly in assembly. Strip tags, before calling into
the assembly helper.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Andy Lutomirski <luto@kernel.org>
Tested-by: Alexander Potapenko <glider@google.com>
---
arch/x86/include/asm/mmu.h | 3 ++
arch/x86/include/asm/mmu_context.h | 11 +++++++
arch/x86/include/asm/uaccess.h | 47 +++++++++++++++++++++++++++---
arch/x86/kernel/process.c | 3 ++
4 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h
index 9a046aacad8d..ed72fcd2292d 100644
--- a/arch/x86/include/asm/mmu.h
+++ b/arch/x86/include/asm/mmu.h
@@ -43,6 +43,9 @@ typedef struct {
/* Active LAM mode: X86_CR3_LAM_U48 or X86_CR3_LAM_U57 or 0 (disabled) */
unsigned long lam_cr3_mask;
+
+ /* Significant bits of the virtual address. Excludes tag bits. */
+ u64 untag_mask;
#endif
struct mutex lock;
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 464cca41d20a..71581cb4811b 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -100,6 +100,12 @@ static inline unsigned long mm_lam_cr3_mask(struct mm_struct *mm)
static inline void dup_lam(struct mm_struct *oldmm, struct mm_struct *mm)
{
mm->context.lam_cr3_mask = oldmm->context.lam_cr3_mask;
+ mm->context.untag_mask = oldmm->context.untag_mask;
+}
+
+static inline void mm_reset_untag_mask(struct mm_struct *mm)
+{
+ mm->context.untag_mask = -1UL;
}
#else
@@ -112,6 +118,10 @@ static inline unsigned long mm_lam_cr3_mask(struct mm_struct *mm)
static inline void dup_lam(struct mm_struct *oldmm, struct mm_struct *mm)
{
}
+
+static inline void mm_reset_untag_mask(struct mm_struct *mm)
+{
+}
#endif
#define enter_lazy_tlb enter_lazy_tlb
@@ -138,6 +148,7 @@ static inline int init_new_context(struct task_struct *tsk,
mm->context.execute_only_pkey = -1;
}
#endif
+ mm_reset_untag_mask(mm);
init_new_context_ldt(mm);
return 0;
}
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 1cc756eafa44..cbb463e9344f 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -7,6 +7,7 @@
#include <linux/compiler.h>
#include <linux/instrumented.h>
#include <linux/kasan-checks.h>
+#include <linux/mm_types.h>
#include <linux/string.h>
#include <asm/asm.h>
#include <asm/page.h>
@@ -21,6 +22,37 @@ static inline bool pagefault_disabled(void);
# define WARN_ON_IN_IRQ()
#endif
+#ifdef CONFIG_X86_64
+/*
+ * Mask out tag bits from the address.
+ *
+ * Magic with the 'sign' allows to untag userspace pointer without any branches
+ * while leaving kernel addresses intact.
+ */
+#define __untagged_addr(mm, addr) ({ \
+ u64 __addr = (__force u64)(addr); \
+ s64 sign = (s64)__addr >> 63; \
+ __addr &= READ_ONCE((mm)->context.untag_mask) | sign; \
+ (__force __typeof__(addr))__addr; \
+})
+
+#define untagged_addr(addr) __untagged_addr(current->mm, addr)
+
+#define untagged_addr_remote(mm, addr) ({ \
+ mmap_assert_locked(mm); \
+ __untagged_addr(mm, addr); \
+})
+
+#define untagged_ptr(ptr) ({ \
+ u64 __ptrval = (__force u64)(ptr); \
+ __ptrval = untagged_addr(__ptrval); \
+ (__force __typeof__(ptr))__ptrval; \
+})
+#else
+#define untagged_addr(addr) (addr)
+#define untagged_ptr(ptr) (ptr)
+#endif
+
/**
* access_ok - Checks if a user space pointer is valid
* @addr: User space pointer to start of block to check
@@ -38,10 +70,10 @@ static inline bool pagefault_disabled(void);
* Return: true (nonzero) if the memory block may be valid, false (zero)
* if it is definitely invalid.
*/
-#define access_ok(addr, size) \
+#define access_ok(addr, size) \
({ \
WARN_ON_IN_IRQ(); \
- likely(__access_ok(addr, size)); \
+ likely(__access_ok(untagged_addr(addr), size)); \
})
#include <asm-generic/access_ok.h>
@@ -127,7 +159,11 @@ extern int __get_user_bad(void);
* Return: zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
-#define get_user(x,ptr) ({ might_fault(); do_get_user_call(get_user,x,ptr); })
+#define get_user(x,ptr) \
+({ \
+ might_fault(); \
+ do_get_user_call(get_user,x,untagged_ptr(ptr)); \
+})
/**
* __get_user - Get a simple variable from user space, with less checking.
@@ -227,7 +263,10 @@ extern void __put_user_nocheck_8(void);
*
* Return: zero on success, or -EFAULT on error.
*/
-#define put_user(x, ptr) ({ might_fault(); do_put_user_call(put_user,x,ptr); })
+#define put_user(x, ptr) ({ \
+ might_fault(); \
+ do_put_user_call(put_user,x,untagged_ptr(ptr)); \
+})
/**
* __put_user - Write a simple value into user space, with less checking.
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 40d156a31676..ef6bde1d40d8 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -47,6 +47,7 @@
#include <asm/frame.h>
#include <asm/unwind.h>
#include <asm/tdx.h>
+#include <asm/mmu_context.h>
#include "process.h"
@@ -367,6 +368,8 @@ void arch_setup_new_exec(void)
task_clear_spec_ssb_noexec(current);
speculation_ctrl_update(read_thread_flags());
}
+
+ mm_reset_untag_mask(current->mm);
}
#ifdef CONFIG_X86_IOPL_IOPERM
--
2.38.2
next prev parent reply other threads:[~2022-12-27 3:08 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-27 3:08 [PATCHv13 00/16] Linear Address Masking enabling Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 01/16] x86: Allow atomic MM_CONTEXT flags setting Kirill A. Shutemov
2023-01-04 19:07 ` Dave Hansen
2022-12-27 3:08 ` [PATCHv13 02/16] x86: CPUID and CR3/CR4 flags for Linear Address Masking Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 03/16] x86/mm: Handle LAM on context switch Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 04/16] mm: Introduce untagged_addr_remote() Kirill A. Shutemov
2022-12-27 3:08 ` Kirill A. Shutemov [this message]
2022-12-27 19:10 ` [PATCHv13 05/16] x86/uaccess: Provide untagged_addr() and remove tags before address check Linus Torvalds
2022-12-31 0:10 ` Kirill A. Shutemov
2022-12-31 0:42 ` Linus Torvalds
2023-01-02 13:55 ` David Laight
2023-01-02 19:05 ` Linus Torvalds
2023-01-03 8:37 ` David Laight
2023-01-07 9:10 ` Kirill A. Shutemov
2023-01-07 17:28 ` Linus Torvalds
2022-12-27 3:08 ` [PATCHv13 06/16] x86/mm: Provide arch_prctl() interface for LAM Kirill A. Shutemov
2023-01-04 19:55 ` Edgecombe, Rick P
2023-01-10 6:17 ` Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 07/16] x86/mm: Reduce untagged_addr() overhead until the first LAM user Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 08/16] mm: Expose untagging mask in /proc/$PID/status Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 09/16] iommu/sva: Replace pasid_valid() helper with mm_valid_pasid() Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 10/16] x86/mm/iommu/sva: Make LAM and SVA mutually exclusive Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 11/16] selftests/x86/lam: Add malloc and tag-bits test cases for linear-address masking Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 12/16] selftests/x86/lam: Add mmap and SYSCALL " Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 13/16] selftests/x86/lam: Add io_uring " Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 14/16] selftests/x86/lam: Add inherit " Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 15/16] selftests/x86/lam: Add ARCH_FORCE_TAGGED_SVA " Kirill A. Shutemov
2022-12-27 3:08 ` [PATCHv13 16/16] selftests/x86/lam: Add test cases for LAM vs thread creation Kirill A. Shutemov
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=20221227030829.12508-6-kirill.shutemov@linux.intel.com \
--to=kirill.shutemov@linux.intel.com \
--cc=ak@linux.intel.com \
--cc=andreyknvl@gmail.com \
--cc=ashok.raj@intel.com \
--cc=bharata@amd.com \
--cc=dave.hansen@linux.intel.com \
--cc=dvyukov@google.com \
--cc=glider@google.com \
--cc=hjl.tools@gmail.com \
--cc=jacob.jun.pan@linux.intel.com \
--cc=kcc@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=peterz@infradead.org \
--cc=rick.p.edgecombe@intel.com \
--cc=ryabinin.a.a@gmail.com \
--cc=tarasmadan@google.com \
--cc=torvalds@linux-foundation.org \
--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