Messages in this thread Patch in this message | | | From | "Chang S. Bae" <> | Subject | [PATCH v10 12/28] x86/fpu/xstate: Update the XSTATE context copy function to support dynamic states | Date | Wed, 25 Aug 2021 08:53:57 -0700 |
| |
ptrace() and signal return paths use XSTATE context copy functions. They allow callers to read 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.
Introduce a new helper to adjust to find the source address correctly.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> Reviewed-by: Len Brown <len.brown@intel.com> Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v9: * Refactor the new code in the loop. (Borislav Petkov) * Move out the copy_uabi_to_xstate() changes (to Patch1,9). (Borislav Petkov)
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 | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 6929db20be0a..bd6a5c746d3f 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -1152,6 +1152,30 @@ static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, membuf_write(to, from_xstate ? xstate : init_xstate, size); } +static void copy_extended_feature(struct membuf *to, struct fpu *fpu, + struct xstate_header *hdr, + int feature_nr) +{ + unsigned int size = xstate_sizes[feature_nr]; + u64 mask = BIT_ULL(feature_nr); + void *from = NULL; + + /* + * Copy from the XSTATE buffer if available. Otherwise, write the + * init value as recorded for legacy states (FP and SSE) or as + * zeros for others. + */ + if (hdr->xfeatures & mask) { + from = __raw_xsave_addr(fpu, feature_nr); + membuf_write(to, from, size); + } else if (XFEATURE_MASK_FPSSE & mask) { + from = __raw_xsave_addr(NULL, feature_nr); + membuf_write(to, from, size); + } else { + membuf_zero(to, size); + } +} + /** * copy_xstate_to_uabi_buf - Copy kernel saved xstate to a UABI buffer * @to: membuf descriptor @@ -1253,10 +1277,7 @@ 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]); + copy_extended_feature(&to, &tsk->thread.fpu, &header, i); } /* * Keep track of the last copied state in the non-compacted -- 2.17.1
| |