Commit 49e4eb41 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Borislav Petkov
Browse files

x86/fpu/xstate: Use fpstate for copy_uabi_to_xstate()



Prepare for dynamically enabled states per task. The function needs to
retrieve the features and sizes which are valid in a fpstate
context. Retrieve them from fpstate.

Move the function declarations to the core header as they are not
required anywhere else.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211013145323.233529986@linutronix.de
parent 3ac8d757
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -129,20 +129,8 @@ extern void __init update_regset_xstate_info(unsigned int size,
					     u64 xstate_mask);

int xfeature_size(int xfeature_nr);
int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf);
int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf);

void xsaves(struct xregs_state *xsave, u64 mask);
void xrstors(struct xregs_state *xsave, u64 mask);

enum xstate_copy_mode {
	XSTATE_COPY_FP,
	XSTATE_COPY_FX,
	XSTATE_COPY_XSAVE,
};

struct membuf;
void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
			     enum xstate_copy_mode mode);

#endif
+1 −1
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ int fpu_copy_kvm_uabi_to_fpstate(struct fpu *fpu, const void *buf, u64 xcr0,
	if (ustate->xsave.header.xfeatures & ~xcr0)
		return -EINVAL;

	ret = copy_uabi_from_kernel_to_xstate(&kstate->regs.xsave, ustate);
	ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
	if (ret)
		return ret;

+2 −3
Original line number Diff line number Diff line
@@ -8,11 +8,11 @@
#include <asm/fpu/api.h>
#include <asm/fpu/signal.h>
#include <asm/fpu/regset.h>
#include <asm/fpu/xstate.h>

#include "context.h"
#include "internal.h"
#include "legacy.h"
#include "xstate.h"

/*
 * The xstateregs_active() routine is the same as the regset_fpregs_active() routine,
@@ -168,8 +168,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
	}

	fpu_force_restore(fpu);
	ret = copy_uabi_from_kernel_to_xstate(&fpu->fpstate->regs.xsave,
					      kbuf ?: tmpbuf);
	ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf);

out:
	vfree(tmpbuf);
+1 −1
Original line number Diff line number Diff line
@@ -375,7 +375,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,

	fpregs = &fpu->fpstate->regs;
	if (use_xsave() && !fx_only) {
		if (copy_sigframe_from_user_to_xstate(&fpregs->xsave, buf_fx))
		if (copy_sigframe_from_user_to_xstate(fpu->fpstate, buf_fx))
			return false;
	} else {
		if (__copy_from_user(&fpregs->fxsave, buf_fx,
+10 −8
Original line number Diff line number Diff line
@@ -463,10 +463,11 @@ int xfeature_size(int xfeature_nr)
}

/* Validate an xstate header supplied by userspace (ptrace or sigreturn) */
static int validate_user_xstate_header(const struct xstate_header *hdr)
static int validate_user_xstate_header(const struct xstate_header *hdr,
				       struct fpstate *fpstate)
{
	/* No unknown or supervisor features may be set */
	if (hdr->xfeatures & ~xfeatures_mask_uabi())
	if (hdr->xfeatures & ~fpstate->user_xfeatures)
		return -EINVAL;

	/* Userspace must use the uncompacted format */
@@ -1115,9 +1116,10 @@ static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
}


static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
			       const void __user *ubuf)
{
	struct xregs_state *xsave = &fpstate->regs.xsave;
	unsigned int offset, size;
	struct xstate_header hdr;
	u64 mask;
@@ -1127,7 +1129,7 @@ static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
	if (copy_from_buffer(&hdr, offset, sizeof(hdr), kbuf, ubuf))
		return -EFAULT;

	if (validate_user_xstate_header(&hdr))
	if (validate_user_xstate_header(&hdr, fpstate))
		return -EINVAL;

	/* Validate MXCSR when any of the related features is in use */
@@ -1182,9 +1184,9 @@ static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
 * Convert from a ptrace standard-format kernel buffer to kernel XSAVE[S]
 * format and copy to the target thread. Used by ptrace and KVM.
 */
int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
{
	return copy_uabi_to_xstate(xsave, kbuf, NULL);
	return copy_uabi_to_xstate(fpstate, kbuf, NULL);
}

/*
@@ -1192,10 +1194,10 @@ int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
 * XSAVE[S] format and copy to the target thread. This is called from the
 * sigreturn() and rt_sigreturn() system calls.
 */
int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave,
int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate,
				      const void __user *ubuf)
{
	return copy_uabi_to_xstate(xsave, NULL, ubuf);
	return copy_uabi_to_xstate(fpstate, NULL, ubuf);
}

static bool validate_independent_components(u64 mask)
Loading