mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2026-01-24 18:43:21 +00:00
Misc fixes:
- Fix a hang in the "kernel IBT no ENDBR" self-test that may trigger
on FRED systems, caused by incomplete FRED state cleanup in the
#CP fault handler.
- Improve TDX (Coco VM) guest unrecoverable error handling to not
potentially leak decrypted memory.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmdxFegRHG1pbmdvQGtl
cm5lbC5vcmcACgkQEnMQ0APhK1g7ug//R9ot2VD/Bd5VaU5OdIkqSbKO5szR3bRz
DU2GmA27wVBDFjmQdJzWqvPs8mIQiDF6bkxxoVFS6KjdDK4dj2BzwfBQ3+v3dweo
OX1+s7wDg3RZtt8ch4yHNk66phimVnBTkg0aWPtgVO0GXE/eE6oTJVe9zw6aB3D8
4vgQSPzgfuIcyPTcmlFDA4LkOpXKVxwhqy/IeZOHaG/zMrMPaY+KZ6hFN/F4Gp3q
46bdPtyM2eFi709bnYDczyneu3osrPhoRkXZQ4xo2+OaH9PUPWWtoVd7mR2GCYuL
gqPerhf06oWzB+sHhrP7i23+LnhUEx1yjEfhtNNkvdCr/YYFVorO+R+2zZvmZjwx
1/FewQKBpQzdJqkHc63h5/wCo8szETejkoTohRvx0QUDJz6UJqASNObQDSdZ/x3j
REtt1ULqg4dKY/NgI0FvpWwTBxfESE7GEldPQ6M0iT9PX6O97DbBq2eObguw/sbT
MYA6yBBD6zGtf/T/ZDCCeGv9qm47H8ZSAPdeWuN2c5Xz+CC+OBiaqZ9VykGmGmsI
L1pmWoo7jU+VpEM0jbHQpRJ2YMHy+fu4wbte2i7pHPVGM5zjcYaNU3GOKa4J/zlh
vXX9q3JLylXQtus4NVLtUqopU3W0M6Me1G9n3FBvFm2E08NYWzHSAOYenz3SioBQ
2lV+098mP4I=
=9Vad
-----END PGP SIGNATURE-----
Merge tag 'x86-urgent-2024-12-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
- Fix a hang in the "kernel IBT no ENDBR" self-test that may trigger
on FRED systems, caused by incomplete FRED state cleanup in the
#CP fault handler
- Improve TDX (Coco VM) guest unrecoverable error handling to not
potentially leak decrypted memory
* tag 'x86-urgent-2024-12-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
virt: tdx-guest: Just leak decrypted memory on unrecoverable errors
x86/fred: Clear WFE in missing-ENDBRANCH #CPs
This commit is contained in:
commit
6cbc4b29eb
@ -81,6 +81,34 @@ static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
|
||||
static __ro_after_init bool ibt_fatal = true;
|
||||
|
||||
/*
|
||||
* By definition, all missing-ENDBRANCH #CPs are a result of WFE && !ENDBR.
|
||||
*
|
||||
* For the kernel IBT no ENDBR selftest where #CPs are deliberately triggered,
|
||||
* the WFE state of the interrupted context needs to be cleared to let execution
|
||||
* continue. Otherwise when the CPU resumes from the instruction that just
|
||||
* caused the previous #CP, another missing-ENDBRANCH #CP is raised and the CPU
|
||||
* enters a dead loop.
|
||||
*
|
||||
* This is not a problem with IDT because it doesn't preserve WFE and IRET doesn't
|
||||
* set WFE. But FRED provides space on the entry stack (in an expanded CS area)
|
||||
* to save and restore the WFE state, thus the WFE state is no longer clobbered,
|
||||
* so software must clear it.
|
||||
*/
|
||||
static void ibt_clear_fred_wfe(struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* No need to do any FRED checks.
|
||||
*
|
||||
* For IDT event delivery, the high-order 48 bits of CS are pushed
|
||||
* as 0s into the stack, and later IRET ignores these bits.
|
||||
*
|
||||
* For FRED, a test to check if fred_cs.wfe is set would be dropped
|
||||
* by compilers.
|
||||
*/
|
||||
regs->fred_cs.wfe = 0;
|
||||
}
|
||||
|
||||
static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
if ((error_code & CP_EC) != CP_ENDBR) {
|
||||
@ -90,6 +118,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
|
||||
if (unlikely(regs->ip == (unsigned long)&ibt_selftest_noendbr)) {
|
||||
regs->ax = 0;
|
||||
ibt_clear_fred_wfe(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -97,6 +126,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
if (!ibt_fatal) {
|
||||
printk(KERN_DEFAULT CUT_HERE);
|
||||
__warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
|
||||
ibt_clear_fred_wfe(regs);
|
||||
return;
|
||||
}
|
||||
BUG();
|
||||
|
||||
@ -124,10 +124,8 @@ static void *alloc_quote_buf(void)
|
||||
if (!addr)
|
||||
return NULL;
|
||||
|
||||
if (set_memory_decrypted((unsigned long)addr, count)) {
|
||||
free_pages_exact(addr, len);
|
||||
if (set_memory_decrypted((unsigned long)addr, count))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user