]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tpm: End any active auth session before shutdown
authorJonathan McDowell <noodles@meta.com>
Fri, 7 Mar 2025 12:25:23 +0000 (12:25 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 Apr 2025 08:17:53 +0000 (10:17 +0200)
[ Upstream commit 1dbf74e00a5f882b04b398399b6def65cd51ef21 ]

Lazy flushing of TPM auth sessions can interact badly with IMA + kexec,
resulting in loaded session handles being leaked across the kexec and
not cleaned up. Fix by ensuring any active auth session is ended before
the TPM is told about the shutdown, matching what is done when
suspending.

Before:

root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
root@debian-qemu-efi:~# kexec --load --kexec-file-syscall …
root@debian-qemu-efi:~# systemctl kexec

root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
- 0x2000000
root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
root@debian-qemu-efi:~#
(repeat kexec steps)
root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
- 0x2000000
- 0x2000001
root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
root@debian-qemu-efi:~#

After:

root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
root@debian-qemu-efi:~# kexec --load --kexec-file-syscall …
root@debian-qemu-efi:~# systemctl kexec

root@debian-qemu-efi:~# tpm2_getcap handles-loaded-session
root@debian-qemu-efi:~# tpm2_getcap handles-saved-session
root@debian-qemu-efi:~#

Signed-off-by: Jonathan McDowell <noodles@meta.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/char/tpm/tpm-chip.c

index 7df7abaf3e526bf7e85ac9dfbaa1087a51d2ab7e..87f01269b9b5332b6d1aeecbbc20e2d77da92b2f 100644 (file)
@@ -300,6 +300,7 @@ int tpm_class_shutdown(struct device *dev)
        down_write(&chip->ops_sem);
        if (chip->flags & TPM_CHIP_FLAG_TPM2) {
                if (!tpm_chip_start(chip)) {
+                       tpm2_end_auth_session(chip);
                        tpm2_shutdown(chip, TPM2_SU_CLEAR);
                        tpm_chip_stop(chip);
                }