From: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> The signal code has a few points where it initializes user FPU state. Remove PKRU from the set of features which are initialized in the FPU code. Use write_pkru() to explicitly initialize PKRU instead of using the fpstate/XSAVE infrastructure. Signed-off-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: x86@xxxxxxxxxx Cc: Andy Lutomirski <luto@xxxxxxxxxx> --- b/arch/x86/kernel/fpu/core.c | 8 +++++--- b/arch/x86/kernel/fpu/signal.c | 5 ++++- b/arch/x86/kernel/signal.c | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff -puN arch/x86/kernel/fpu/core.c~no-pkru-in-fpu__clear_user_states arch/x86/kernel/fpu/core.c --- a/arch/x86/kernel/fpu/core.c~no-pkru-in-fpu__clear_user_states 2021-06-22 14:49:10.026051754 -0700 +++ b/arch/x86/kernel/fpu/core.c 2021-06-22 14:49:10.039051754 -0700 @@ -209,7 +209,8 @@ static inline void fpstate_init_xstate(s * XRSTORS requires these bits set in xcomp_bv, or it will * trigger #GP: */ - xsave->header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | xfeatures_mask_all; + xsave->header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT | + xfeatures_mask_fpstate(); } static inline void fpstate_init_fxstate(struct fxregs_state *fx) @@ -389,8 +390,9 @@ void fpu__clear_user_states(struct fpu * os_xrstor(&fpu->state.xsave, xfeatures_mask_supervisor()); } - /* Reset user states in registers. */ - load_fpregs_from_init_fpstate(xfeatures_mask_restore_user()); + /* Reset user registers maintained in fpstate. */ + load_fpregs_from_init_fpstate(xfeatures_mask_fpstate() & + xfeatures_mask_restore_user()); /* * Now all FPU registers have their desired values. Inform the FPU diff -puN arch/x86/kernel/fpu/signal.c~no-pkru-in-fpu__clear_user_states arch/x86/kernel/fpu/signal.c --- a/arch/x86/kernel/fpu/signal.c~no-pkru-in-fpu__clear_user_states 2021-06-22 14:49:10.031051754 -0700 +++ b/arch/x86/kernel/fpu/signal.c 2021-06-22 14:49:10.040051754 -0700 @@ -437,6 +437,7 @@ int fpu__restore_sig(void __user *buf, i int ret; if (unlikely(!buf)) { + write_pkru(pkru_get_init_value()); fpu__clear_user_states(¤t->thread.fpu); return 0; } @@ -468,8 +469,10 @@ int fpu__restore_sig(void __user *buf, i ret = __fpu_restore_sig(buf, buf_fx, ia32_fxstate); out: - if (unlikely(ret)) + if (unlikely(ret)) { + write_pkru(pkru_get_init_value()); fpu__clear_user_states(¤t->thread.fpu); + } return ret; } diff -puN arch/x86/kernel/signal.c~no-pkru-in-fpu__clear_user_states arch/x86/kernel/signal.c --- a/arch/x86/kernel/signal.c~no-pkru-in-fpu__clear_user_states 2021-06-22 14:49:10.033051754 -0700 +++ b/arch/x86/kernel/signal.c 2021-06-22 14:49:10.043051754 -0700 @@ -835,6 +835,7 @@ handle_signal(struct ksignal *ksig, stru /* * Ensure the signal handler starts with the new fpu state. */ + write_pkru(pkru_get_init_value()); fpu__clear_user_states(fpu); } signal_setup_done(failed, ksig, stepping); _