Re: [PATCH v2 2/4] x86/process: Add a debug interface to change LAM tag width

From: Borislav Petkov

Date: Tue Feb 24 2026 - 16:26:38 EST


On February 24, 2026 1:22:07 PM UTC, Maciej Wieczor-Retman <m.wieczorretman@xxxxx> wrote:
>From: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
>
>While shortening the tag bits to converge the specifications of LAM and
>ChkTag, the 6 bit wide LAM (Linear Address Masking) tags should still be
>available to use. Since using this tag width is likely going to be for
>debug purposes only, using debugfs is the best choice.
>
>Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
>---
>Changelog v2:
>- Extend buf size from 2 to 3 and remove unused variable.
>
> arch/x86/kernel/process_64.c | 55 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 55 insertions(+)
>
>diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
>index 4a217f13ab90..1d5b8c8851f1 100644
>--- a/arch/x86/kernel/process_64.c
>+++ b/arch/x86/kernel/process_64.c
>@@ -41,6 +41,7 @@
> #include <linux/ftrace.h>
> #include <linux/syscalls.h>
> #include <linux/iommu.h>
>+#include <linux/debugfs.h>
>
> #include <asm/processor.h>
> #include <asm/pkru.h>
>@@ -802,6 +803,60 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr)
>
> unsigned long lam_available_bits = LAM_DEFAULT_BITS;
>
>+static ssize_t lam_bits_read_file(struct file *file, char __user *user_buf,
>+ size_t count, loff_t *ppos)
>+{
>+ char buf[3];
>+ unsigned int len;
>+
>+ len = sprintf(buf, "%ld\n", lam_available_bits);
>+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
>+}
>+
>+/*
>+ * Writing a number to this file changes the used lam tag width. Valid values
>+ * are 4 bit tag width and 6 bit tag width - the second, non-default one is
>+ * meant mostly for debug and shall be deprecated in the future.
>+ */
>+static ssize_t lam_bits_write_file(struct file *file,
>+ const char __user *user_buf, size_t count,
>+ loff_t *ppos)
>+{
>+ char buf[32];
>+ ssize_t len;
>+ u8 bits;
>+
>+ len = min(count, sizeof(buf) - 1);
>+ if (copy_from_user(buf, user_buf, len))
>+ return -EFAULT;
>+
>+ buf[len] = '\0';
>+ if (kstrtou8(buf, 0, &bits))
>+ return -EINVAL;
>+
>+ switch (bits) {
>+ case LAM_DEFAULT_BITS:
>+ case LAM_MAX_BITS:
>+ lam_available_bits = bits;
>+ return count;
>+ default:
>+ return -EINVAL;
>+ }
>+}
>+
>+static const struct file_operations fops_lam_bits = {
>+ .read = lam_bits_read_file,
>+ .write = lam_bits_write_file,
>+};
>+
>+static int __init create_lam_available_bits(void)
>+{
>+ debugfs_create_file("lam_available_bits", 0600,
>+ arch_debugfs_dir, NULL, &fops_lam_bits);
>+ return 0;
>+}
>+late_initcall(create_lam_available_bits);
>+
> static void enable_lam_func(void *__mm)
> {
> struct mm_struct *mm = __mm;

The moment someone starts using this, it becomes an ABI no matter whether it is in debugfs or not.

So why do we *really* want it?
--
Small device. Typos and formatting crap