On Wed, Jul 20, 2022 at 10:19:36AM +0200, Alexander Potapenko wrote: > > > > long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) > > > > { > > > > int ret = 0; > > > > @@ -829,7 +883,11 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) > > > > case ARCH_MAP_VDSO_64: > > > > return prctl_map_vdso(&vdso_image_64, arg2); > > > > #endif > > > > - > > > > + case ARCH_GET_UNTAG_MASK: > > > > + return put_user(task->mm->context.untag_mask, > > > > + (unsigned long __user *)arg2); > > > > > > Can we have ARCH_GET_UNTAG_MASK return the same error value (ENODEV or > > > EINVAL) as ARCH_ENABLE_TAGGED_ADDR in the case the host doesn't > > > support LAM? > > > After all, the mask does not make much sense in this case. > > > > I'm not sure about this. > > > > As it is ARCH_GET_UNTAG_MASK returns -1UL mask if LAM is not present or > > not enabled. Applying this mask will give correct result for both. > > Is anyone going to use this mask if tagging is unsupported? > Tools like HWASan won't even try to proceed in that case. I can imagine the code that tries to be indifferent to whether a pointer has tags. It gets mask from ARCH_GET_UNTAG_MASK and applies it to the pointer without any conditions. > > Why is -ENODEV better here? Looks like just more work for userspace. > > This boils down to the question of detecting LAM support I raised previously. > It's nice to have a syscall without side effects to check whether LAM > can be enabled at all (e.g. one can do the check in the parent process > and conditionally enable LAM in certain, but not all, child processes) > CPUID won't help here, because the presence of the LAM bit in CPUID > doesn't guarantee its support in the kernel, and every other solution > is more complicated than just issuing a system call. > > Note that TBI has PR_GET_TAGGED_ADDR_CTRL, which can be used to detect > the presence of memory tagging support. I would rather make enumeration explicit: diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 38164a05c23c..a31e27b95b19 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h @@ -22,5 +22,6 @@ #define ARCH_GET_UNTAG_MASK 0x4001 #define ARCH_ENABLE_TAGGED_ADDR 0x4002 +#define ARCH_GET_MAX_TAG_BITS 0x4003 #endif /* _ASM_X86_PRCTL_H */ diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index cfa2e42a135a..2e4df63b775f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -911,6 +911,13 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) (unsigned long __user *)arg2); case ARCH_ENABLE_TAGGED_ADDR: return prctl_enable_tagged_addr(task->mm, arg2); + case ARCH_GET_MAX_TAG_BITS: + if (!cpu_feature_enabled(X86_FEATURE_LAM)) + return put_user(0, (unsigned long __user *)arg2); + else if (lam_u48_allowed()) + return put_user(15, (unsigned long __user *)arg2); + else + return put_user(6, (unsigned long __user *)arg2); default: ret = -EINVAL; break; -- Kirill A. Shutemov