Messages in this thread Patch in this message |  | | From | "Chang S. Bae" <> | Subject | [PATCH v5 16/28] x86/fpu/xstate: Support ptracer-induced xstate buffer expansion | Date | Sun, 23 May 2021 12:32:47 -0700 |
| |
ptrace() may update xstate data before the target task has taken an XFD fault and expanded the xstate buffer. Detect this case and allocate a sufficient buffer to support the request. Also, disable the (now unnecessary) associated first-use fault.
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 v4: * Improved the condition check for the expansion. * Simplified the XSTATE_BV retrieval. * Updated the code comment.
Changes from v3: * Removed 'no functional changes' in the changelog. (Borislav Petkov)
Changes from v2: * Updated the changelog with task->fpu removed. (Borislav Petkov) * Updated the code comments. --- arch/x86/kernel/fpu/regset.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index ee27df4caed6..b2fac4b5e483 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -122,6 +122,38 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, xsave = &fpu->state->xsave; + /* + * When a ptracer attempts to write any dynamic user state in the target buffer but not + * sufficiently allocated, it dynamically expands the buffer. + * + * Check if the expansion is possibly needed. + */ + if (xfeatures_mask_user_dynamic && + ((fpu->state_mask & xfeatures_mask_user_dynamic) != xfeatures_mask_user_dynamic)) { + unsigned int offset, size; + u64 state_mask; + + offset = offsetof(struct xregs_state, header); + size = sizeof(u64); + + /* Retrieve XSTATE_BV. */ + if (kbuf) { + memcpy(&state_mask, kbuf + offset, size); + } else { + ret = __copy_from_user(&state_mask, ubuf + offset, size); + if (ret) + return ret; + } + + /* Expand the xstate buffer based on the XSTATE_BV. */ + state_mask &= xfeatures_mask_user_dynamic; + if (state_mask) { + ret = alloc_xstate_buffer(fpu, state_mask); + if (ret) + return ret; + } + } + fpu__prepare_write(fpu); if (using_compacted_format()) { -- 2.17.1
|  |