CVE-2026-45941
Description
In the Linux kernel, the following vulnerability has been resolved:
tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
get_burstcount() can return -EBUSY on timeout. When this happens, the function returns directly without releasing the locality that was acquired at the beginning of tpm_tis_i2c_send().
Use goto out_err to ensure proper cleanup when get_burstcount() fails.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel TPM I2C Infineon driver leaks locality on get_burstcount() timeout, causing denial of service.
Vulnerability
In the Linux kernel's TPM I2C Infineon driver (drivers/char/tpm/tpm_i2c_infineon.c), the function tpm_tis_i2c_send() acquires a TPM locality at the start but does not release it if get_burstcount() fails with -EBUSY due to a timeout. This leads to a locality leak. The issue was introduced in an older version and is fixed by commit 948966e546f29af04391d98b8e378e4a7670c1c1 [1].
Exploitation
An attacker with the ability to send TPM commands that trigger a timeout in get_burstcount() can cause the driver to exit without releasing the locality. No authentication is required beyond access to the TPM device, but physical proximity or local access may be needed depending on the system configuration.
Impact
The leaked locality prevents other TPM operations from acquiring that locality, effectively blocking TPM access for other processes or drivers. This results in a denial of service (DoS) condition for the TPM subsystem. No privilege escalation or information disclosure is known.
Mitigation
The fix is included in the Linux kernel stable tree as commit 948966e546f29af04391d98b8e378e4a7670c1c1 [1]. Users should update to a kernel version containing this commit. No workaround is available without patching.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
161bb8f8826d07tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index fd3c3661e64663..b1cfd2da5eb3ec 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
8f124c5582d4tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index a19d32cb4e942c..cabc9e1b49321c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
948966e546f2tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 81d8a78dc65528..3675faa4a00c75 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
1a22048c1117tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
2f7a665e1323tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
c24c9c4cab11tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index a19d32cb4e942c..cabc9e1b49321c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
a61b8412e3ebtpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 81d8a78dc65528..3675faa4a00c75 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
bbd6e97c836ctpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
1a22048c1117tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
c24c9c4cab11tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index a19d32cb4e942c..cabc9e1b49321c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
bbd6e97c836ctpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
2f7a665e1323tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index bdf1f329a67946..8b7d32de0b2ef9 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -544,8 +544,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
1bb8f8826d07tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index fd3c3661e64663..b1cfd2da5eb3ec 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
8f124c5582d4tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index a19d32cb4e942c..cabc9e1b49321c 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
948966e546f2tpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 81d8a78dc65528..3675faa4a00c75 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
a61b8412e3ebtpm: tpm_i2c_infineon: Fix locality leak on get_burstcount() failure
1 file changed · +4 −3
drivers/char/tpm/tpm_i2c_infineon.c+4 −3 modifieddiff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 81d8a78dc65528..3675faa4a00c75 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -543,8 +543,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) burstcnt = get_burstcount(chip); /* burstcnt < 0 = TPM is busy */ - if (burstcnt < 0) - return burstcnt; + if (burstcnt < 0) { + rc = burstcnt; + goto out_err; + } if (burstcnt > (len - 1 - count)) burstcnt = len - 1 - count; -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing error-path cleanup: when get_burstcount() returns -EBUSY (timeout), the function returns directly without releasing the TPM locality that was acquired at the start of tpm_tis_i2c_send()."
Attack vector
An attacker who can cause the Infineon I2C TIS TPM to time out during a send operation (e.g., by holding the TPM busy or inducing I2C communication delays) triggers the bug. When get_burstcount() returns -EBUSY, the function tpm_tis_i2c_send() returns early without releasing the locality [patch_id=2661157]. This leaks the locality, potentially preventing subsequent TPM commands from acquiring it, leading to denial of service. No special privileges are required beyond the ability to interact with the TPM device.
Affected code
The bug is in `tpm_tis_i2c_send()` in `drivers/char/tpm/tpm_i2c_infineon.c` [patch_id=2661157]. The error check for `get_burstcount()` at approximately line 546 used `return burstcnt;` instead of jumping to the existing cleanup path.
What the fix does
The patch replaces the direct `return burstcnt` with `rc = burstcnt; goto out_err;` [patch_id=2661157]. The `out_err` label (already present in the function) handles locality release via `tpm_tis_i2c_release_locality(chip, priv->locality)`. This ensures that when get_burstcount() fails, the locality is properly freed before returning the error code, closing the leak.
Preconditions
- configThe system must use an Infineon I2C TIS TPM device with the tpm_i2c_infineon driver.
- inputThe attacker must be able to cause the TPM to be busy or unresponsive long enough for get_burstcount() to time out.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- git.kernel.org/stable/c/1a22048c1117cdfac185ba450aba67ed6b65dc87nvd
- git.kernel.org/stable/c/1bb8f8826d0748b4b92a98fb6b6dfe52081739f5nvd
- git.kernel.org/stable/c/2f7a665e1323359d99c74301d1e180f5e2c40181nvd
- git.kernel.org/stable/c/8f124c5582d443ac9fb690db26d08cab5d6ba76envd
- git.kernel.org/stable/c/948966e546f29af04391d98b8e378e4a7670c1c1nvd
- git.kernel.org/stable/c/a61b8412e3eb8b71646dba867e8252d8560a1a27nvd
- git.kernel.org/stable/c/bbd6e97c836cbeb9606d7b7e5dcf8a1d89525713nvd
- git.kernel.org/stable/c/c24c9c4cab11858f22f309521ba7ea5b1e7385f2nvd
News mentions
0No linked articles in our index yet.