Re: [tpmdd-devel] [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs

2016-03-13 Thread Jarkko Sakkinen
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: [tpmdd-devel] [PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs

2016-03-13 Thread Jarkko Sakkinen
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

2016-03-12 Thread Stefan Berger

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

2016-03-12 Thread Stefan Berger

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

2016-03-12 Thread Jarkko Sakkinen
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

2016-03-12 Thread Jarkko Sakkinen
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

2016-03-11 Thread Stefan Berger
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 

[PATCH v7 08/10] tpm: Proxy driver for supporting multiple emulated TPMs

2016-03-11 Thread Stefan Berger
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
+ */