static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru)
 {
-       if (use_xsave())
-               return xsave_to_user_sigframe(buf);
+       int err = 0;
+
+       if (use_xsave()) {
+               err = xsave_to_user_sigframe(buf);
+               if (!err)
+                       err = update_pkru_in_sigframe(buf, pkru);
+               return err;
+       }
+
        if (use_fxsr())
                return fxsave_to_user_sigframe((struct fxregs_state __user *) buf);
        else
 
        unsigned long math_size = 0;
        unsigned long sp = regs->sp;
        unsigned long buf_fx = 0;
-       u32 pkru = read_pkru();
+       u32 pkru;
 
        /* redzone */
        if (!ia32_frame)
                return (void __user *)-1L;
        }
 
+       /* Update PKRU to enable access to the alternate signal stack. */
+       pkru = sig_prepare_pkru();
        /* save i387 and extended state */
-       if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru))
+       if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru)) {
+               /*
+                * Restore PKRU to the original, user-defined value; disable
+                * extra pkeys enabled for the alternate signal stack, if any.
+                */
+               write_pkru(pkru);
                return (void __user *)-1L;
+       }
 
        return (void __user *)sp;
 }