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....@intel.com>
Reviewed-by: Len Brown <len.br...@intel.com>
Cc: x...@kernel.org
Cc: linux-kernel@vger.kernel.org
---
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 | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index ee27df4caed6..ec6cbb75010e 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -122,6 +122,35 @@ int xstateregs_set(struct task_struct *target, const 
struct user_regset *regset,
 
        xsave = &fpu->state->xsave;
 
+       /*
+        * When a ptracer attempts to write any state in the target buffer but 
not
+        * sufficiently allocated, it dynamically expands the buffer.
+        */
+       if (count > get_xstate_size(fpu->state_mask)) {
+               unsigned int offset, size;
+               struct xstate_header hdr;
+               u64 mask;
+
+               offset = offsetof(struct xregs_state, header);
+               size = sizeof(hdr);
+
+               /* Retrieve XSTATE_BV */
+               if (kbuf) {
+                       memcpy(&hdr, kbuf + offset, size);
+               } else {
+                       ret = __copy_from_user(&hdr, ubuf + offset, size);
+                       if (ret)
+                               return ret;
+               }
+
+               mask = hdr.xfeatures & xfeatures_mask_user_dynamic;
+               if (!mask) {
+                       ret = alloc_xstate_buffer(fpu, mask);
+                       if (ret)
+                               return ret;
+               }
+       }
+
        fpu__prepare_write(fpu);
 
        if (using_compacted_format()) {
-- 
2.17.1

Reply via email to