Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86/pkeys: Update PKRU to enable all pkeys before XSAVE

If the alternate signal stack is protected by a different PKEY than the
current execution stack, copying XSAVE data to the sigaltstack will fail
if its PKEY is not enabled in the PKRU register.

It's unknown which pkey was used by the application for the altstack, so
enable all PKEYS before XSAVE.

But this updated PKRU value is also pushed onto the sigframe, which
means the register value restored from sigcontext will be different from
the user-defined one, which is incorrect.

Fix that by overwriting the PKRU value on the sigframe with the original,
user-defined PKRU.

Signed-off-by: Aruna Ramakrishna <aruna.ramakrishna@oracle.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20240802061318.2140081-4-aruna.ramakrishna@oracle.com

authored by

Aruna Ramakrishna and committed by
Thomas Gleixner
70044df2 84ee6e8d

+19 -4
+9 -2
arch/x86/kernel/fpu/signal.c
··· 168 168 169 169 static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru) 170 170 { 171 - if (use_xsave()) 172 - return xsave_to_user_sigframe(buf); 171 + int err = 0; 172 + 173 + if (use_xsave()) { 174 + err = xsave_to_user_sigframe(buf); 175 + if (!err) 176 + err = update_pkru_in_sigframe(buf, pkru); 177 + return err; 178 + } 179 + 173 180 if (use_fxsr()) 174 181 return fxsave_to_user_sigframe((struct fxregs_state __user *) buf); 175 182 else
+10 -2
arch/x86/kernel/signal.c
··· 102 102 unsigned long math_size = 0; 103 103 unsigned long sp = regs->sp; 104 104 unsigned long buf_fx = 0; 105 - u32 pkru = read_pkru(); 105 + u32 pkru; 106 106 107 107 /* redzone */ 108 108 if (!ia32_frame) ··· 157 157 return (void __user *)-1L; 158 158 } 159 159 160 + /* Update PKRU to enable access to the alternate signal stack. */ 161 + pkru = sig_prepare_pkru(); 160 162 /* save i387 and extended state */ 161 - if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru)) 163 + if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size, pkru)) { 164 + /* 165 + * Restore PKRU to the original, user-defined value; disable 166 + * extra pkeys enabled for the alternate signal stack, if any. 167 + */ 168 + write_pkru(pkru); 162 169 return (void __user *)-1L; 170 + } 163 171 164 172 return (void __user *)sp; 165 173 }