ptrace() may update xstate data before the target task has taken an XFD
fault and expanded the context switch buffer. Detect this case and allocate
a sufficient buffer to support the request. Also, disable the (now
unnecessary) associated first-use fault.

No functional change until the kernel supports dynamic user states.

Signed-off-by: Chang S. Bae <[email protected]>
Reviewed-by: Len Brown <[email protected]>
Cc: [email protected]
Cc: [email protected]
---
Changes from v2:
* Updated the changelog with task->fpu removed. (Boris 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 8d863240b9c6..16ff8ac765c1 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -125,6 +125,35 @@ int xstateregs_set(struct task_struct *target, const 
struct user_regset *regset,
 
        xsave = __xsave(fpu);
 
+       /*
+        * 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