mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
The TPM character devices expose a sequential command/response
interface, but their open handlers leave FMODE_PREAD and FMODE_PWRITE
enabled.
After a command leaves a response pending, pread(fd, buf, 16, 0x1400)
passes 0x1400 as *off to tpm_common_read(). The transfer length is
bounded by response_length, but the offset is used unchecked when
forming data_buffer + *off. A sufficiently large offset therefore causes
an out-of-bounds heap read through copy_to_user() and, if the copy
succeeds, an out-of-bounds zero-write through the following memset().
Positional I/O does not provide coherent semantics for this interface.
An arbitrary pread offset cannot represent how much of a response has
been consumed sequentially. The write callback always stores a command
at the start of data_buffer, while pwrite() does not update file->f_pos
and can leave the sequential read cursor stale.
Call nonseekable_open() from both open handlers. This removes
FMODE_PREAD and FMODE_PWRITE, causing positional reads and writes to
fail with -ESPIPE before reaching the TPM callbacks, and explicitly
marks the files non-seekable. Normal read() and write() continue to use
the existing sequential f_pos cursor, leaving the response state machine
unchanged.
Tested on Linux 6.12 with KASAN and a swtpm TPM2 device:
- sequential partial reads returned the complete response
- pread() and preadv() with offset 0x1400 returned -ESPIPE
- pwrite() and pwritev() with offset zero returned -ESPIPE
- the pending response remained intact after the rejected operations
- a subsequent normal command/response cycle completed normally
- no KASAN report was produced.
Fixes:
|
||
|---|---|---|
| .. | ||
| eventlog | ||
| st33zp24 | ||
| Kconfig | ||
| Makefile | ||
| tpm_atmel.c | ||
| tpm_crb_ffa.c | ||
| tpm_crb_ffa.h | ||
| tpm_crb.c | ||
| tpm_ftpm_tee.c | ||
| tpm_ftpm_tee.h | ||
| tpm_i2c_atmel.c | ||
| tpm_i2c_infineon.c | ||
| tpm_i2c_nuvoton.c | ||
| tpm_ibmvtpm.c | ||
| tpm_ibmvtpm.h | ||
| tpm_infineon.c | ||
| tpm_loongson.c | ||
| tpm_nsc.c | ||
| tpm_ppi.c | ||
| tpm_svsm.c | ||
| tpm_tis_core.c | ||
| tpm_tis_core.h | ||
| tpm_tis_i2c_cr50.c | ||
| tpm_tis_i2c.c | ||
| tpm_tis_spi_cr50.c | ||
| tpm_tis_spi_main.c | ||
| tpm_tis_spi.h | ||
| tpm_tis_synquacer.c | ||
| tpm_tis.c | ||
| tpm_vtpm_proxy.c | ||
| tpm-buf.c | ||
| tpm-chip.c | ||
| tpm-dev-common.c | ||
| tpm-dev.c | ||
| tpm-dev.h | ||
| tpm-interface.c | ||
| tpm-sysfs.c | ||
| tpm.h | ||
| tpm1-cmd.c | ||
| tpm2-cmd.c | ||
| tpm2-sessions.c | ||
| tpm2-space.c | ||
| tpmrm-dev.c | ||
| xen-tpmfront.c | ||