From: Maciej Wieczor-Retman <[email protected]>

While the user should expect 4 bit tags from the lam interface current
hardware supports 6 bit tags. Such tag width is also used internally by
the kernel so the kernel-hardware treatment of addresses that came from
userspace is consistent.

Add a procfs file with the hardware supported untag mask. It may be used
by debuggers to recreate hardware or kernel handling of user pointers.
At the same time the returned value from this file shouldn't be relied
on by regular lam user programs since it might change with future
hardware. For a stable interface they should use the ARCH_GET_UNTAG_MASK
arch_prctl() syscall instead.

Signed-off-by: Maciej Wieczor-Retman <[email protected]>
---
Changelog v7:
- Add the patch to the series.

 arch/x86/Kconfig             |  1 +
 arch/x86/kernel/process_64.c | 18 ++++++++++++++++++
 fs/proc/Kconfig              |  4 ++++
 fs/proc/base.c               |  6 ++++++
 include/linux/uaccess.h      |  5 +++++
 5 files changed, 34 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e2df1b147184..1ec303cca1ab 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2194,6 +2194,7 @@ config ADDRESS_MASKING
        bool "Linear Address Masking support"
        depends on X86_64
        depends on COMPILE_TEST || !CPU_MITIGATIONS # wait for LASS
+       select PROC_ADDRESS_MASKING if PROC_FS
        help
          Linear Address Masking (LAM) modifies the checking that is applied
          to 64-bit linear addresses, allowing software to use of the
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 8b8aaf1d740b..44c4a80fc658 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -800,6 +800,24 @@ static long prctl_map_vdso(const struct vdso_image *image, 
unsigned long addr)
 #define LAM_TAG_BITS           4
 #define LAM_UNTAG_MASK         ~GENMASK(60, 57)
 
+#ifdef CONFIG_PROC_ADDRESS_MASKING
+
+int proc_address_mask(struct seq_file *s, struct pid_namespace *ns,
+                     struct pid *pid, struct task_struct *tsk)
+{
+       struct mm_struct *mm;
+
+       mm = get_task_mm(tsk);
+       if (mm) {
+               seq_printf(s, "0x%llx\n", mm->context.untag_mask);
+               mmput(mm);
+       }
+
+       return 0;
+}
+
+#endif
+
 static void enable_lam_func(void *__mm)
 {
        struct mm_struct *mm = __mm;
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig
index 6ae966c561e7..0094e185a7b2 100644
--- a/fs/proc/Kconfig
+++ b/fs/proc/Kconfig
@@ -127,3 +127,7 @@ config PROC_PID_ARCH_STATUS
 config PROC_CPU_RESCTRL
        def_bool n
        depends on PROC_FS
+
+config PROC_ADDRESS_MASKING
+       def_bool n
+       depends on PROC_FS
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4c863d17dfb4..9483ad4197e1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -3421,6 +3421,9 @@ static const struct pid_entry tgid_base_stuff[] = {
        ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
        ONE("ksm_stat",  S_IRUSR, proc_pid_ksm_stat),
 #endif
+#ifdef CONFIG_PROC_ADDRESS_MASKING
+       ONE("address_mask", S_IRUSR, proc_address_mask),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -3755,6 +3758,9 @@ static const struct pid_entry tid_base_stuff[] = {
        ONE("ksm_merging_pages",  S_IRUSR, proc_pid_ksm_merging_pages),
        ONE("ksm_stat",  S_IRUSR, proc_pid_ksm_stat),
 #endif
+#ifdef CONFIG_PROC_ADDRESS_MASKING
+       ONE("address_mask", S_IRUSR, proc_address_mask),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 4fe63169d5a2..c02d254a1a1e 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -869,4 +869,9 @@ void __noreturn usercopy_abort(const char *name, const char 
*detail,
                               unsigned long len);
 #endif
 
+#ifdef CONFIG_PROC_ADDRESS_MASKING
+int proc_address_mask(struct seq_file *s, struct pid_namespace *ns,
+                     struct pid *pid, struct task_struct *tsk);
+#endif
+
 #endif         /* __LINUX_UACCESS_H__ */
-- 
2.53.0



Reply via email to