Commit 67840ad0 authored by Rick Edgecombe's avatar Rick Edgecombe Committed by Dave Hansen
Browse files

x86/shstk: Add ARCH_SHSTK_STATUS



CRIU and GDB need to get the current shadow stack and WRSS enablement
status. This information is already available via /proc/pid/status, but
this is inconvenient for CRIU because it involves parsing the text output
in an area of the code where this is difficult. Provide a status
arch_prctl(), ARCH_SHSTK_STATUS for retrieving the status. Have arg2 be a
userspace address, and make the new arch_prctl simply copy the features
out to userspace.

Suggested-by: default avatarMike Rapoport <rppt@kernel.org>
Signed-off-by: default avatarRick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Acked-by: default avatarMike Rapoport (IBM) <rppt@kernel.org>
Tested-by: default avatarPengfei Xu <pengfei.xu@intel.com>
Tested-by: default avatarJohn Allen <john.allen@amd.com>
Tested-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/all/20230613001108.3040476-43-rick.p.edgecombe%40intel.com
parent 680ed2f1
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -79,6 +79,11 @@ arch_prctl(ARCH_SHSTK_UNLOCK, unsigned long features)
    Unlock features. 'features' is a mask of all features to unlock. All
    bits set are processed, unset bits are ignored. Only works via ptrace.

arch_prctl(ARCH_SHSTK_STATUS, unsigned long addr)
    Copy the currently enabled features to the address passed in addr. The
    features are described using the bits passed into the others in
    'features'.

The return values are as follows. On success, return 0. On error, errno can
be::

@@ -86,6 +91,7 @@ be::
        -ENOTSUPP if the feature is not supported by the hardware or
         kernel.
        -EINVAL arguments (non existing feature, etc)
        -EFAULT if could not copy information back to userspace

The feature's bits supported are::

+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@ struct thread_shstk {
	u64	size;
};

long shstk_prctl(struct task_struct *task, int option, unsigned long features);
long shstk_prctl(struct task_struct *task, int option, unsigned long arg2);
void reset_thread_features(void);
unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clone_flags,
				       unsigned long stack_size);
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#define ARCH_SHSTK_DISABLE		0x5002
#define ARCH_SHSTK_LOCK			0x5003
#define ARCH_SHSTK_UNLOCK		0x5004
#define ARCH_SHSTK_STATUS		0x5005

/* ARCH_SHSTK_ features bits */
#define ARCH_SHSTK_SHSTK		(1ULL <<  0)
+1 −0
Original line number Diff line number Diff line
@@ -900,6 +900,7 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
	case ARCH_SHSTK_DISABLE:
	case ARCH_SHSTK_LOCK:
	case ARCH_SHSTK_UNLOCK:
	case ARCH_SHSTK_STATUS:
		return shstk_prctl(task, option, arg2);
	default:
		ret = -EINVAL;
+7 −1
Original line number Diff line number Diff line
@@ -482,8 +482,14 @@ SYSCALL_DEFINE3(map_shadow_stack, unsigned long, addr, unsigned long, size, unsi
	return alloc_shstk(addr, aligned_size, size, set_tok);
}

long shstk_prctl(struct task_struct *task, int option, unsigned long features)
long shstk_prctl(struct task_struct *task, int option, unsigned long arg2)
{
	unsigned long features = arg2;

	if (option == ARCH_SHSTK_STATUS) {
		return put_user(task->thread.features, (unsigned long __user *)arg2);
	}

	if (option == ARCH_SHSTK_LOCK) {
		task->thread.features_locked |= features;
		return 0;