[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210630060226.24652-12-chang.seok.bae@intel.com>
Date: Tue, 29 Jun 2021 23:02:11 -0700
From: "Chang S. Bae" <chang.seok.bae@...el.com>
To: bp@...e.de, luto@...nel.org, tglx@...utronix.de, mingo@...nel.org,
x86@...nel.org
Cc: len.brown@...el.com, dave.hansen@...el.com, jing2.liu@...el.com,
ravi.v.shankar@...el.com, linux-kernel@...r.kernel.org,
chang.seok.bae@...el.com
Subject: [PATCH v6 11/26] x86/fpu/xstate: Update the XSTATE context copy function to support dynamic states
ptrace() and signal return paths use XSTATE context copy functions. They
allow callers to read (or write) XSTATE values in the target's buffer. With
dynamic user states, a component's position in the buffer may vary and the
init fpstate is not always large enough to cover all the states.
Adjust the helpers to find a component's offset correctly. Also, update the
copy loop in the ptrace read path to support dynamic states.
Signed-off-by: Chang S. Bae <chang.seok.bae@...el.com>
Reviewed-by: Len Brown <len.brown@...el.com>
Cc: x86@...nel.org
Cc: linux-kernel@...r.kernel.org
---
Changes from v5:
* Updated to ensure xstate_bv aligned with the target.
* Rewrote the xstate copy loop, for the ptrace() read path, in an open
code.
* Adjusted the changelog.
Changes from v3:
* Cleaned up the code change with more comments.
* Removed 'no functional change' in the changelog. (Borislav Petkov)
Changes from v2:
* Updated the changelog with task->fpu removed. (Borislav Petkov)
---
arch/x86/kernel/fpu/xstate.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 58e7567dc3cc..8939345778a7 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1287,6 +1287,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
zerofrom = offsetof(struct xregs_state, extended_state_area);
for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
+ u64 mask = BIT_ULL(i);
/*
* The ptrace buffer is in non-compacted XSAVE format.
* In non-compacted format disabled features still occupy
@@ -1294,7 +1295,7 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
* compacted init_fpstate. The gap tracking will zero this
* later.
*/
- if (!(xfeatures_mask_uabi() & BIT_ULL(i)))
+ if (!(xfeatures_mask_uabi() & mask))
continue;
/*
@@ -1314,10 +1315,24 @@ void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
pkru.pkru = tsk->thread.pkru;
membuf_write(&to, &pkru, sizeof(pkru));
} else {
- copy_feature(header.xfeatures & BIT_ULL(i), &to,
- __raw_xsave_addr(&tsk->thread.fpu, i),
- __raw_xsave_addr(NULL, i),
- xstate_sizes[i]);
+ unsigned int size = xstate_sizes[i];
+ void *from = NULL;
+
+ /*
+ * Copy the xstate if available. Otherwise, copy the
+ * non-zero init states for legacy states (FP and
+ * SSE) or fill zeros.
+ */
+
+ if (header.xfeatures & mask)
+ from = __raw_xsave_addr(&tsk->thread.fpu, i);
+ else if (XFEATURE_MASK_FPSSE & mask)
+ from = __raw_xsave_addr(NULL, i);
+
+ if (from)
+ membuf_write(&to, from, size);
+ else
+ membuf_zero(&to, size);
}
/*
* Keep track of the last copied state in the non-compacted
@@ -1359,6 +1374,8 @@ static int copy_uabi_to_xstate(struct fpu *fpu, const void *kbuf,
if (validate_user_xstate_header(&hdr))
return -EINVAL;
+ hdr.xfeatures &= fpu->state_mask;
+
/* Validate MXCSR when any of the related features is in use */
mask = XFEATURE_MASK_FP | XFEATURE_MASK_SSE | XFEATURE_MASK_YMM;
if (hdr.xfeatures & mask) {
@@ -1385,6 +1402,9 @@ static int copy_uabi_to_xstate(struct fpu *fpu, const void *kbuf,
if (hdr.xfeatures & mask) {
void *dst = __raw_xsave_addr(fpu, i);
+ if (!dst)
+ continue;
+
offset = xstate_offsets[i];
size = xstate_sizes[i];
--
2.17.1
Powered by blists - more mailing lists