Re: [tpmdd-devel] [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On Sat, Mar 12, 2016 at 06:27:13PM -0500, Stefan Berger wrote: >Jarkko Sakkinenwrote on 03/12/2016 >01:51:54 PM: > >> >> On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: >> > This patch implements a proxy driver for supporting multiple emulated >TPMs >> > in a system. >> > >> > The driver implements a device /dev/vtpmx that is used to created >> > a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side >that >> > is accessed using a file descriptor returned by an ioctl. >> > The device /dev/tpmX is the usual TPM device created by the core TPM >> > driver. Applications or kernel subsystems can send TPM commands to it >> > and the corresponding server-side file descriptor receives these >> > commands and delivers them to an emulated TPM. >> >> With my test script [1] running on QEMU and TPM 2.0 simulator running on >the >> host side I get this: >> >> $ python tpm2-simulator-vtpm --host=10.0.2.2 >> cmd >> 80 01 00 00 00 0c 00 00 01 44 00 00 >> rsp >> 80 01 00 00 00 0a 00 00 00 00 >> Traceback (most recent call last): >> File "tpm2-simulator-vtpm", line 85, in >> main() >> File "tpm2-simulator-vtpm", line 80, in main >> resp = client.send_cmd(stream) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd >> rsp = self.simulator.send_cmd(cmd) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd >> raise SimulatorError("Empty response") >> tpm2.SimulatorError: Empty response >> >> However, the process does not exit before the read call expires: >> >> $ python tpm2-list-handles >> Traceback (most recent call last): >> File "tpm2-list-handles", line 61, in >> main() >> File "tpm2-list-handles", line 51, in main >> handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, >tpm2.HR_LOADED_SESSION) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap >> next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt >> rsp = self.send_cmd(cmd)[10:] >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd >> rsp = f.read() >> IOError: [Errno 62] Timer expired >> >> The server side stays stuck unti this happens. > >This fix should solve the problem: > >diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c >b/drivers/char/tpm/tpm_vtpm_proxy.c >index d73944e..01e5070 100644 >--- a/drivers/char/tpm/tpm_vtpm_proxy.c >+++ b/drivers/char/tpm/tpm_vtpm_proxy.c >@@ -456,10 +456,10 @@ err_delete_proxy_dev: > */ > static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) > { >- tpm_chip_unregister(proxy_dev->chip); >- >vtpm_proxy_fops_undo_open(proxy_dev); > >+ tpm_chip_unregister(proxy_dev->chip); >+ >vtpm_proxy_delete_proxy_dev(proxy_dev); > } > >Can you let me know whether this gets it working for you? I'd prepare a >v9. So is the deadlock such that: * tpm_chip_unregister() tries to write lock ops_sem. * tpm_transmit() holds read lock to ops_sem. This takes two minutes if no timeouts are calculated. And is the effect of moving vtpm_proxy_fops_undo_open() upwards such that vtpm_proxy_tpm_req_canceled() starts returning true, which in effect breaks the loop in tpm_transmit()? Yeah, the fix as a code change is very simple but I had to use perf probe to verify this so maybe a comment there would be in place to tell why tpm_chip_unregister() must be called last (write lock). > Stefan /Jarkko
Re: [tpmdd-devel] [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On Sat, Mar 12, 2016 at 06:27:13PM -0500, Stefan Berger wrote: >Jarkko Sakkinen wrote on 03/12/2016 >01:51:54 PM: > >> >> On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: >> > This patch implements a proxy driver for supporting multiple emulated >TPMs >> > in a system. >> > >> > The driver implements a device /dev/vtpmx that is used to created >> > a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side >that >> > is accessed using a file descriptor returned by an ioctl. >> > The device /dev/tpmX is the usual TPM device created by the core TPM >> > driver. Applications or kernel subsystems can send TPM commands to it >> > and the corresponding server-side file descriptor receives these >> > commands and delivers them to an emulated TPM. >> >> With my test script [1] running on QEMU and TPM 2.0 simulator running on >the >> host side I get this: >> >> $ python tpm2-simulator-vtpm --host=10.0.2.2 >> cmd >> 80 01 00 00 00 0c 00 00 01 44 00 00 >> rsp >> 80 01 00 00 00 0a 00 00 00 00 >> Traceback (most recent call last): >> File "tpm2-simulator-vtpm", line 85, in >> main() >> File "tpm2-simulator-vtpm", line 80, in main >> resp = client.send_cmd(stream) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd >> rsp = self.simulator.send_cmd(cmd) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd >> raise SimulatorError("Empty response") >> tpm2.SimulatorError: Empty response >> >> However, the process does not exit before the read call expires: >> >> $ python tpm2-list-handles >> Traceback (most recent call last): >> File "tpm2-list-handles", line 61, in >> main() >> File "tpm2-list-handles", line 51, in main >> handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, >tpm2.HR_LOADED_SESSION) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap >> next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt >> rsp = self.send_cmd(cmd)[10:] >> File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd >> rsp = f.read() >> IOError: [Errno 62] Timer expired >> >> The server side stays stuck unti this happens. > >This fix should solve the problem: > >diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c >b/drivers/char/tpm/tpm_vtpm_proxy.c >index d73944e..01e5070 100644 >--- a/drivers/char/tpm/tpm_vtpm_proxy.c >+++ b/drivers/char/tpm/tpm_vtpm_proxy.c >@@ -456,10 +456,10 @@ err_delete_proxy_dev: > */ > static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) > { >- tpm_chip_unregister(proxy_dev->chip); >- >vtpm_proxy_fops_undo_open(proxy_dev); > >+ tpm_chip_unregister(proxy_dev->chip); >+ >vtpm_proxy_delete_proxy_dev(proxy_dev); > } > >Can you let me know whether this gets it working for you? I'd prepare a >v9. So is the deadlock such that: * tpm_chip_unregister() tries to write lock ops_sem. * tpm_transmit() holds read lock to ops_sem. This takes two minutes if no timeouts are calculated. And is the effect of moving vtpm_proxy_fops_undo_open() upwards such that vtpm_proxy_tpm_req_canceled() starts returning true, which in effect breaks the loop in tpm_transmit()? Yeah, the fix as a code change is very simple but I had to use perf probe to verify this so maybe a comment there would be in place to tell why tpm_chip_unregister() must be called last (write lock). > Stefan /Jarkko
Re: [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On 03/12/2016 01:51 PM, Jarkko Sakkinen wrote: On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: This patch implements a proxy driver for supporting multiple emulated TPMs in a system. The driver implements a device /dev/vtpmx that is used to created a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that is accessed using a file descriptor returned by an ioctl. The device /dev/tpmX is the usual TPM device created by the core TPM driver. Applications or kernel subsystems can send TPM commands to it and the corresponding server-side file descriptor receives these commands and delivers them to an emulated TPM. With my test script [1] running on QEMU and TPM 2.0 simulator running on the host side I get this: $ python tpm2-simulator-vtpm --host=10.0.2.2 cmd 80 01 00 00 00 0c 00 00 01 44 00 00 rsp 80 01 00 00 00 0a 00 00 00 00 Traceback (most recent call last): File "tpm2-simulator-vtpm", line 85, in main() File "tpm2-simulator-vtpm", line 80, in main resp = client.send_cmd(stream) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd rsp = self.simulator.send_cmd(cmd) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd raise SimulatorError("Empty response") tpm2.SimulatorError: Empty response However, the process does not exit before the read call expires: $ python tpm2-list-handles Traceback (most recent call last): File "tpm2-list-handles", line 61, in main() File "tpm2-list-handles", line 51, in main handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt rsp = self.send_cmd(cmd)[10:] File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd rsp = f.read() IOError: [Errno 62] Timer expired The server side stays stuck unti this happens. This fix should solve the problem: diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index d73944e..01e5070 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -456,10 +456,10 @@ err_delete_proxy_dev: */ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) { - tpm_chip_unregister(proxy_dev->chip); - vtpm_proxy_fops_undo_open(proxy_dev); + tpm_chip_unregister(proxy_dev->chip); + vtpm_proxy_delete_proxy_dev(proxy_dev); } Can you let me know whether this gets it working for you? I'd prepare a v9. Stefan
Re: [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On 03/12/2016 01:51 PM, Jarkko Sakkinen wrote: On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: This patch implements a proxy driver for supporting multiple emulated TPMs in a system. The driver implements a device /dev/vtpmx that is used to created a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that is accessed using a file descriptor returned by an ioctl. The device /dev/tpmX is the usual TPM device created by the core TPM driver. Applications or kernel subsystems can send TPM commands to it and the corresponding server-side file descriptor receives these commands and delivers them to an emulated TPM. With my test script [1] running on QEMU and TPM 2.0 simulator running on the host side I get this: $ python tpm2-simulator-vtpm --host=10.0.2.2 cmd 80 01 00 00 00 0c 00 00 01 44 00 00 rsp 80 01 00 00 00 0a 00 00 00 00 Traceback (most recent call last): File "tpm2-simulator-vtpm", line 85, in main() File "tpm2-simulator-vtpm", line 80, in main resp = client.send_cmd(stream) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd rsp = self.simulator.send_cmd(cmd) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd raise SimulatorError("Empty response") tpm2.SimulatorError: Empty response However, the process does not exit before the read call expires: $ python tpm2-list-handles Traceback (most recent call last): File "tpm2-list-handles", line 61, in main() File "tpm2-list-handles", line 51, in main handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt rsp = self.send_cmd(cmd)[10:] File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd rsp = f.read() IOError: [Errno 62] Timer expired The server side stays stuck unti this happens. This fix should solve the problem: diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index d73944e..01e5070 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -456,10 +456,10 @@ err_delete_proxy_dev: */ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev) { - tpm_chip_unregister(proxy_dev->chip); - vtpm_proxy_fops_undo_open(proxy_dev); + tpm_chip_unregister(proxy_dev->chip); + vtpm_proxy_delete_proxy_dev(proxy_dev); } Can you let me know whether this gets it working for you? I'd prepare a v9. Stefan
Re: [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: > This patch implements a proxy driver for supporting multiple emulated TPMs > in a system. > > The driver implements a device /dev/vtpmx that is used to created > a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that > is accessed using a file descriptor returned by an ioctl. > The device /dev/tpmX is the usual TPM device created by the core TPM > driver. Applications or kernel subsystems can send TPM commands to it > and the corresponding server-side file descriptor receives these > commands and delivers them to an emulated TPM. With my test script [1] running on QEMU and TPM 2.0 simulator running on the host side I get this: $ python tpm2-simulator-vtpm --host=10.0.2.2 cmd 80 01 00 00 00 0c 00 00 01 44 00 00 rsp 80 01 00 00 00 0a 00 00 00 00 Traceback (most recent call last): File "tpm2-simulator-vtpm", line 85, in main() File "tpm2-simulator-vtpm", line 80, in main resp = client.send_cmd(stream) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd rsp = self.simulator.send_cmd(cmd) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd raise SimulatorError("Empty response") tpm2.SimulatorError: Empty response However, the process does not exit before the read call expires: $ python tpm2-list-handles Traceback (most recent call last): File "tpm2-list-handles", line 61, in main() File "tpm2-list-handles", line 51, in main handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt rsp = self.send_cmd(cmd)[10:] File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd rsp = f.read() IOError: [Errno 62] Timer expired The server side stays stuck unti this happens. [1] git://git.infradead.org/users/jjs/tpm2-scripts.git /Jarkko > Signed-off-by: Stefan Berger> CC: linux-kernel@vger.kernel.org > CC: linux-...@vger.kernel.org > CC: linux-...@vger.kernel.org > --- > drivers/char/tpm/Kconfig | 10 + > drivers/char/tpm/Makefile | 1 + > drivers/char/tpm/tpm_vtpm_proxy.c | 567 > ++ > include/uapi/linux/Kbuild | 1 + > include/uapi/linux/vtpm_proxy.h | 42 +++ > 5 files changed, 621 insertions(+) > create mode 100644 drivers/char/tpm/tpm_vtpm_proxy.c > create mode 100644 include/uapi/linux/vtpm_proxy.h > > diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig > index 3b84a8b..0eac596 100644 > --- a/drivers/char/tpm/Kconfig > +++ b/drivers/char/tpm/Kconfig > @@ -122,5 +122,15 @@ config TCG_CRB > from within Linux. To compile this driver as a module, choose > M here; the module will be called tpm_crb. > > +config TCG_VTPM_PROXY > + tristate "VTPM Proxy Interface" > + depends on TCG_TPM > + ---help--- > + This driver proxies for an emulated TPM (vTPM) running in userspace. > + A device /dev/vtpmx is provided that creates a device pair > + /dev/vtpmX and a server-side file descriptor on which the vTPM > + can receive commands. > + > + > source "drivers/char/tpm/st33zp24/Kconfig" > endif # TCG_TPM > diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile > index 56e8f1f..98de5e6 100644 > --- a/drivers/char/tpm/Makefile > +++ b/drivers/char/tpm/Makefile > @@ -23,3 +23,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o > obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/ > obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o > obj-$(CONFIG_TCG_CRB) += tpm_crb.o > +obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o > diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c > b/drivers/char/tpm/tpm_vtpm_proxy.c > new file mode 100644 > index 000..d73944e > --- /dev/null > +++ b/drivers/char/tpm/tpm_vtpm_proxy.c > @@ -0,0 +1,567 @@ > +/* > + * Copyright (C) 2015, 2016 IBM Corporation > + * > + * Author: Stefan Berger > + * > + * Maintained by: > + * > + * Device driver for vTPM (vTPM proxy driver) > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation, version 2 of the > + * License. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "tpm.h" > + > +#define VTPM_PROXY_REQ_COMPLETE_FLAG BIT(0) > + > +struct proxy_dev { > + struct tpm_chip *chip; > + > + u32 flags; /* public API flags */ > + > + wait_queue_head_t wq; > + > + struct mutex buf_lock; /* protect buffer and flags */ > + > + long state; /* internal state */ > +#define STATE_OPENED_FLAG
Re: [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
On Fri, Mar 11, 2016 at 09:51:03PM -0500, Stefan Berger wrote: > This patch implements a proxy driver for supporting multiple emulated TPMs > in a system. > > The driver implements a device /dev/vtpmx that is used to created > a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that > is accessed using a file descriptor returned by an ioctl. > The device /dev/tpmX is the usual TPM device created by the core TPM > driver. Applications or kernel subsystems can send TPM commands to it > and the corresponding server-side file descriptor receives these > commands and delivers them to an emulated TPM. With my test script [1] running on QEMU and TPM 2.0 simulator running on the host side I get this: $ python tpm2-simulator-vtpm --host=10.0.2.2 cmd 80 01 00 00 00 0c 00 00 01 44 00 00 rsp 80 01 00 00 00 0a 00 00 00 00 Traceback (most recent call last): File "tpm2-simulator-vtpm", line 85, in main() File "tpm2-simulator-vtpm", line 80, in main resp = client.send_cmd(stream) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 454, in send_cmd rsp = self.simulator.send_cmd(cmd) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 436, in send_cmd raise SimulatorError("Empty response") tpm2.SimulatorError: Empty response However, the process does not exit before the read call expires: $ python tpm2-list-handles Traceback (most recent call last): File "tpm2-list-handles", line 61, in main() File "tpm2-list-handles", line 51, in main handles += client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 782, in get_cap next_handles, more_data = self.__get_cap_cnt(cap, pt, 1) File "/home/tpmdd/tpm2-scripts/tpm2.py", line 766, in __get_cap_cnt rsp = self.send_cmd(cmd)[10:] File "/home/tpmdd/tpm2-scripts/tpm2.py", line 458, in send_cmd rsp = f.read() IOError: [Errno 62] Timer expired The server side stays stuck unti this happens. [1] git://git.infradead.org/users/jjs/tpm2-scripts.git /Jarkko > Signed-off-by: Stefan Berger > CC: linux-kernel@vger.kernel.org > CC: linux-...@vger.kernel.org > CC: linux-...@vger.kernel.org > --- > drivers/char/tpm/Kconfig | 10 + > drivers/char/tpm/Makefile | 1 + > drivers/char/tpm/tpm_vtpm_proxy.c | 567 > ++ > include/uapi/linux/Kbuild | 1 + > include/uapi/linux/vtpm_proxy.h | 42 +++ > 5 files changed, 621 insertions(+) > create mode 100644 drivers/char/tpm/tpm_vtpm_proxy.c > create mode 100644 include/uapi/linux/vtpm_proxy.h > > diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig > index 3b84a8b..0eac596 100644 > --- a/drivers/char/tpm/Kconfig > +++ b/drivers/char/tpm/Kconfig > @@ -122,5 +122,15 @@ config TCG_CRB > from within Linux. To compile this driver as a module, choose > M here; the module will be called tpm_crb. > > +config TCG_VTPM_PROXY > + tristate "VTPM Proxy Interface" > + depends on TCG_TPM > + ---help--- > + This driver proxies for an emulated TPM (vTPM) running in userspace. > + A device /dev/vtpmx is provided that creates a device pair > + /dev/vtpmX and a server-side file descriptor on which the vTPM > + can receive commands. > + > + > source "drivers/char/tpm/st33zp24/Kconfig" > endif # TCG_TPM > diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile > index 56e8f1f..98de5e6 100644 > --- a/drivers/char/tpm/Makefile > +++ b/drivers/char/tpm/Makefile > @@ -23,3 +23,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o > obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/ > obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o > obj-$(CONFIG_TCG_CRB) += tpm_crb.o > +obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o > diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c > b/drivers/char/tpm/tpm_vtpm_proxy.c > new file mode 100644 > index 000..d73944e > --- /dev/null > +++ b/drivers/char/tpm/tpm_vtpm_proxy.c > @@ -0,0 +1,567 @@ > +/* > + * Copyright (C) 2015, 2016 IBM Corporation > + * > + * Author: Stefan Berger > + * > + * Maintained by: > + * > + * Device driver for vTPM (vTPM proxy driver) > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation, version 2 of the > + * License. > + * > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "tpm.h" > + > +#define VTPM_PROXY_REQ_COMPLETE_FLAG BIT(0) > + > +struct proxy_dev { > + struct tpm_chip *chip; > + > + u32 flags; /* public API flags */ > + > + wait_queue_head_t wq; > + > + struct mutex buf_lock; /* protect buffer and flags */ > + > + long state; /* internal state */ > +#define STATE_OPENED_FLAGBIT(0) > +#define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator
[PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
This patch implements a proxy driver for supporting multiple emulated TPMs in a system. The driver implements a device /dev/vtpmx that is used to created a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that is accessed using a file descriptor returned by an ioctl. The device /dev/tpmX is the usual TPM device created by the core TPM driver. Applications or kernel subsystems can send TPM commands to it and the corresponding server-side file descriptor receives these commands and delivers them to an emulated TPM. Signed-off-by: Stefan BergerCC: linux-kernel@vger.kernel.org CC: linux-...@vger.kernel.org CC: linux-...@vger.kernel.org --- drivers/char/tpm/Kconfig | 10 + drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_vtpm_proxy.c | 567 ++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/vtpm_proxy.h | 42 +++ 5 files changed, 621 insertions(+) create mode 100644 drivers/char/tpm/tpm_vtpm_proxy.c create mode 100644 include/uapi/linux/vtpm_proxy.h diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 3b84a8b..0eac596 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -122,5 +122,15 @@ config TCG_CRB from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_crb. +config TCG_VTPM_PROXY + tristate "VTPM Proxy Interface" + depends on TCG_TPM + ---help--- + This driver proxies for an emulated TPM (vTPM) running in userspace. + A device /dev/vtpmx is provided that creates a device pair + /dev/vtpmX and a server-side file descriptor on which the vTPM + can receive commands. + + source "drivers/char/tpm/st33zp24/Kconfig" endif # TCG_TPM diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 56e8f1f..98de5e6 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/ obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o obj-$(CONFIG_TCG_CRB) += tpm_crb.o +obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c new file mode 100644 index 000..d73944e --- /dev/null +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -0,0 +1,567 @@ +/* + * Copyright (C) 2015, 2016 IBM Corporation + * + * Author: Stefan Berger + * + * Maintained by: + * + * Device driver for vTPM (vTPM proxy driver) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tpm.h" + +#define VTPM_PROXY_REQ_COMPLETE_FLAG BIT(0) + +struct proxy_dev { + struct tpm_chip *chip; + + u32 flags; /* public API flags */ + + wait_queue_head_t wq; + + struct mutex buf_lock; /* protect buffer and flags */ + + long state; /* internal state */ +#define STATE_OPENED_FLAGBIT(0) +#define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */ + + size_t req_len; /* length of queued TPM request */ + size_t resp_len; /* length of queued TPM response */ + u8 buffer[TPM_BUFSIZE]; /* request/response buffer */ +}; + + +static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev); + +/* + * Functions related to 'server side' + */ + +/** + * vtpm_proxy_fops_read - Read TPM commands on 'server side' + * + * Return value: + * Number of bytes read or negative error code + */ +static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf, + size_t count, loff_t *off) +{ + struct proxy_dev *proxy_dev = filp->private_data; + size_t len; + int sig, rc; + + sig = wait_event_interruptible(proxy_dev->wq, proxy_dev->req_len != 0); + if (sig) + return -EINTR; + + mutex_lock(_dev->buf_lock); + + len = proxy_dev->req_len; + + if (count < len) { + mutex_unlock(_dev->buf_lock); + pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n", +count, len); + return -EIO; + } + + rc = copy_to_user(buf, proxy_dev->buffer, len); + memset(proxy_dev->buffer, 0, len); + proxy_dev->req_len = 0; + + if (!rc) + proxy_dev->state |= STATE_WAIT_RESPONSE_FLAG; + + mutex_unlock(_dev->buf_lock); + + if (rc) + return -EFAULT; + + return len; +} + +/** + * vtpm_proxy_fops_write - Write TPM responses on 'server
[PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs
This patch implements a proxy driver for supporting multiple emulated TPMs in a system. The driver implements a device /dev/vtpmx that is used to created a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that is accessed using a file descriptor returned by an ioctl. The device /dev/tpmX is the usual TPM device created by the core TPM driver. Applications or kernel subsystems can send TPM commands to it and the corresponding server-side file descriptor receives these commands and delivers them to an emulated TPM. Signed-off-by: Stefan Berger CC: linux-kernel@vger.kernel.org CC: linux-...@vger.kernel.org CC: linux-...@vger.kernel.org --- drivers/char/tpm/Kconfig | 10 + drivers/char/tpm/Makefile | 1 + drivers/char/tpm/tpm_vtpm_proxy.c | 567 ++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/vtpm_proxy.h | 42 +++ 5 files changed, 621 insertions(+) create mode 100644 drivers/char/tpm/tpm_vtpm_proxy.c create mode 100644 include/uapi/linux/vtpm_proxy.h diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 3b84a8b..0eac596 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -122,5 +122,15 @@ config TCG_CRB from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_crb. +config TCG_VTPM_PROXY + tristate "VTPM Proxy Interface" + depends on TCG_TPM + ---help--- + This driver proxies for an emulated TPM (vTPM) running in userspace. + A device /dev/vtpmx is provided that creates a device pair + /dev/vtpmX and a server-side file descriptor on which the vTPM + can receive commands. + + source "drivers/char/tpm/st33zp24/Kconfig" endif # TCG_TPM diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 56e8f1f..98de5e6 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/ obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o obj-$(CONFIG_TCG_CRB) += tpm_crb.o +obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c new file mode 100644 index 000..d73944e --- /dev/null +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -0,0 +1,567 @@ +/* + * Copyright (C) 2015, 2016 IBM Corporation + * + * Author: Stefan Berger + * + * Maintained by: + * + * Device driver for vTPM (vTPM proxy driver) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tpm.h" + +#define VTPM_PROXY_REQ_COMPLETE_FLAG BIT(0) + +struct proxy_dev { + struct tpm_chip *chip; + + u32 flags; /* public API flags */ + + wait_queue_head_t wq; + + struct mutex buf_lock; /* protect buffer and flags */ + + long state; /* internal state */ +#define STATE_OPENED_FLAGBIT(0) +#define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */ + + size_t req_len; /* length of queued TPM request */ + size_t resp_len; /* length of queued TPM response */ + u8 buffer[TPM_BUFSIZE]; /* request/response buffer */ +}; + + +static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev); + +/* + * Functions related to 'server side' + */ + +/** + * vtpm_proxy_fops_read - Read TPM commands on 'server side' + * + * Return value: + * Number of bytes read or negative error code + */ +static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf, + size_t count, loff_t *off) +{ + struct proxy_dev *proxy_dev = filp->private_data; + size_t len; + int sig, rc; + + sig = wait_event_interruptible(proxy_dev->wq, proxy_dev->req_len != 0); + if (sig) + return -EINTR; + + mutex_lock(_dev->buf_lock); + + len = proxy_dev->req_len; + + if (count < len) { + mutex_unlock(_dev->buf_lock); + pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n", +count, len); + return -EIO; + } + + rc = copy_to_user(buf, proxy_dev->buffer, len); + memset(proxy_dev->buffer, 0, len); + proxy_dev->req_len = 0; + + if (!rc) + proxy_dev->state |= STATE_WAIT_RESPONSE_FLAG; + + mutex_unlock(_dev->buf_lock); + + if (rc) + return -EFAULT; + + return len; +} + +/** + * vtpm_proxy_fops_write - Write TPM responses on 'server side' + * + * Return value: + * Number of bytes read or negative error value + */