linux/drivers/char
Peter Huewe 8abffa895c tpm: Propagate error from tpm_transmit to fix a timeout hang
commit abce9ac292 upstream.

tpm_write calls tpm_transmit without checking the return value and
assigns the return value unconditionally to chip->pending_data, even if
it's an error value.
This causes three bugs.

So if we write to /dev/tpm0 with a tpm_param_size bigger than
TPM_BUFSIZE=0x1000 (e.g. 0x100a)
and a bufsize also bigger than TPM_BUFSIZE (e.g. 0x100a)
tpm_transmit returns -E2BIG which is assigned to chip->pending_data as
-7, but tpm_write returns that TPM_BUFSIZE bytes have been successfully
been written to the TPM, altough this is not true (bug #1).

As we did write more than than TPM_BUFSIZE bytes but tpm_write reports
that only TPM_BUFSIZE bytes have been written the vfs tries to write
the remaining bytes (in this case 10 bytes) to the tpm device driver via
tpm_write which then blocks at

 /* cannot perform a write until the read has cleared
 either via tpm_read or a user_read_timer timeout */
 while (atomic_read(&chip->data_pending) != 0)
	 msleep(TPM_TIMEOUT);

for 60 seconds, since data_pending is -7 and nobody is able to
read it (since tpm_read luckily checks if data_pending is greater than
0) (#bug 2).

After that the remaining bytes are written to the TPM which are
interpreted by the tpm as a normal command. (bug #3)
So if the last bytes of the command stream happen to be a e.g.
tpm_force_clear this gets accidentally sent to the TPM.

This patch fixes all three bugs, by propagating the error code of
tpm_write and returning -E2BIG if the input buffer is too big,
since the response from the tpm for a truncated value is bogus anyway.
Moreover it returns -EBUSY to userspace if there is a response ready to be
read.

Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-10-21 09:28:01 -07:00
..
agp char/agp: add another Ironlake host bridge 2012-06-17 11:21:22 -07:00
hw_random hwrng: atmel-rng - fix data valid check 2012-06-22 11:37:15 -07:00
ipmi Merge branch 'akpm' (Andrew's patch-bomb) 2012-03-28 17:19:28 -07:00
mwave Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
pcmcia Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
tpm tpm: Propagate error from tpm_transmit to fix a timeout hang 2012-10-21 09:28:01 -07:00
xilinx_hwicap Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
apm-emulation.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm 2012-04-05 17:34:30 -07:00
applicom.c
applicom.h
bfin-otp.c
bsr.c treewide: Convert uses of struct resource to resource_size(ptr) 2011-06-10 14:55:36 +02:00
ds1302.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
ds1620.c
dsp56k.c
dtlk.c
efirtc.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
generic_nvram.c drivers: fix up various ->llseek() implementations 2011-07-20 20:47:58 -04:00
genrtc.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
hangcheck-timer.c
hpet.c printk(): add KERN_CONT where needed in hpet and vt code 2012-04-09 10:30:39 -07:00
i8k.c module_param: make bool parameters really bool (drivers & misc) 2012-01-13 09:32:20 +10:30
Kconfig tty: delete briq_panel.c driver 2012-03-08 10:45:55 -08:00
lp.c Merge branch 'x86-x32-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2012-03-29 18:12:23 -07:00
Makefile tty: delete briq_panel.c driver 2012-03-08 10:45:55 -08:00
mbcs.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
mbcs.h Fix common misspellings 2011-03-31 11:26:23 -03:00
mem.c switch device_get_devnode() and ->devnode() to umode_t * 2012-01-03 22:54:55 -05:00
misc.c switch device_get_devnode() and ->devnode() to umode_t * 2012-01-03 22:54:55 -05:00
mmtimer.c posix-timers: Cleanup namespace 2011-02-02 15:28:19 +01:00
msm_smd_pkt.c drivers/char/msm_smd_pkt.c: don't use IS_ERR() 2011-08-25 16:25:33 -07:00
mspec.c Redefine ATOMIC_INIT and ATOMIC64_INIT to drop the casts 2012-08-15 08:10:04 -07:00
nsc_gpio.c
nvram.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
nwbutton.c Fix common misspellings 2011-03-31 11:26:23 -03:00
nwbutton.h
nwflash.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
pc8736x_gpio.c
ppdev.c drivers/char/ppdev.c: put gotten port value 2011-05-26 17:12:37 -07:00
ps3flash.c drivers/char: Add module.h to those who were using it implicitly 2011-10-31 19:31:40 -04:00
ramoops.c char/ramoops: included linux/err.h twice 2012-02-24 14:16:43 -08:00
random.c random: mix in architectural randomness in extract_buf() 2012-08-15 08:10:30 -07:00
raw.c switch device_get_devnode() and ->devnode() to umode_t * 2012-01-03 22:54:55 -05:00
rtc.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
scx200_gpio.c
snsc_event.c
snsc.c
snsc.h headers: kobject.h redux 2011-01-10 08:51:44 -08:00
sonypi.c Remove all #inclusions of asm/system.h 2012-03-28 18:30:03 +01:00
tb0219.c
tile-srom.c tile-srom.c driver: minor code cleanup 2012-04-02 12:14:10 -04:00
tlclk.c char: Fix typo in tlclk.c 2012-02-09 23:09:37 +01:00
toshiba.c
ttyprintk.c TTY: ttyprintk, don't touch behind tty->write_buf 2012-10-07 08:32:24 -07:00
uv_mmtimer.c BKL: remove extraneous #include <smp_lock.h> 2010-11-17 08:59:32 -08:00
virtio_console.c virtio: console: tell host of open ports after resume from s3/s4 2012-05-17 12:14:33 +03:00