Re: [PATCH v9 2/4] tpm: Proxy driver for supporting multiple emulated TPMs
On Mon, Apr 11, 2016 at 11:43:58AM +0300, Jarkko Sakkinen wrote: > On Thu, Apr 07, 2016 at 11:49:44AM -0400, Stefan Berger wrote: > > On 04/07/2016 08:35 AM, Jarkko Sakkinen wrote: > > >On Tue, Mar 29, 2016 at 02:19:12PM -0400, 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. > > >> > > >>Signed-off-by: Stefan Berger > > >>CC: linux-kernel@vger.kernel.org > > >>CC: linux-...@vger.kernel.org > > >>CC: linux-...@vger.kernel.org > > >Reviewed-by: Jarkko Sakkinen > > >Tested-by: Jarkko Sakkinen > > > > Thanks. So I can post a v10 where I have to re-introduce the priv field but > > put it into the tpm_chip struct. Obviously it needs this field. I am not > > sure whether you'll let me take the Reviewed-by and Tested-by, though? > > Lets hold for them then. I'll do retest when I get the new series. Lets just fix the sysfs stuff the same way we fixed ppi and be done with this issue. Something that looks kinda like this untested thing: diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index a7c3473c3421..51e898be4307 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -36,7 +36,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, int i, rc; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); tpm_cmd.header.in = tpm_readpubek_header; err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, @@ -92,7 +92,7 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, ssize_t rc; int i, j, num_pcrs; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS"); @@ -222,7 +222,7 @@ static DEVICE_ATTR_RO(caps); static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); if (chip == NULL) return 0; @@ -234,7 +234,7 @@ static DEVICE_ATTR_WO(cancel); static ssize_t durations_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); if (chip->duration[TPM_LONG] == 0) return 0; @@ -251,7 +251,7 @@ static DEVICE_ATTR_RO(durations); static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_chip *chip = dev_get_drvdata(dev); + struct tpm_chip *chip = to_tpm_chip(dev); return sprintf(buf, "%d %d %d %d [%s]\n", jiffies_to_usecs(chip->timeout_a), @@ -283,22 +283,33 @@ static const struct attribute_group tpm_dev_group = { int tpm_sysfs_add_device(struct tpm_chip *chip) { - int err; - err = sysfs_create_group(&chip->dev.parent->kobj, -&tpm_dev_group); + const struct attribute **i; - if (err) - dev_err(&chip->dev, - "failed to create sysfs attributes, %d\n", err); - return err; + chip->groups[chip->groups_cnt++] = &tpm_dev_group; + if (chip->flags & TPM_CHIP_FLAG_TPM2) + return 0; + + for (i = tpm_dev_attrs; *i != NULL; ++i) { + rc = __compat_only_sysfs_link_entry_to_kobj( + &chip->dev.parent->kobj, &chip->dev.kobj, (*i)->name); + if (rc && rc != -ENOENT) { + tpm_sysfs_del_device(chip); + return rc; + } + } + + return 0; } void tpm_sysfs_del_device(struct tpm_chip *chip) { - /* The sysfs routines rely on an implicit tpm_try_get_ops, this -* function is called before ops is null'd and the sysfs core -* synchronizes this removal so that no callbacks are running or can -* run again + const struct attribute **i; + + /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del +* is called before ops is null'd and the sysfs core synchronizes this +
Re: [PATCH v9 2/4] tpm: Proxy driver for supporting multiple emulated TPMs
On Thu, Apr 07, 2016 at 11:49:44AM -0400, Stefan Berger wrote: > On 04/07/2016 08:35 AM, Jarkko Sakkinen wrote: > >On Tue, Mar 29, 2016 at 02:19:12PM -0400, 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. > >> > >>Signed-off-by: Stefan Berger > >>CC: linux-kernel@vger.kernel.org > >>CC: linux-...@vger.kernel.org > >>CC: linux-...@vger.kernel.org > >Reviewed-by: Jarkko Sakkinen > >Tested-by: Jarkko Sakkinen > > Thanks. So I can post a v10 where I have to re-introduce the priv field but > put it into the tpm_chip struct. Obviously it needs this field. I am not > sure whether you'll let me take the Reviewed-by and Tested-by, though? Lets hold for them then. I'll do retest when I get the new series. >Stefan /Jarkko
Re: [PATCH v9 2/4] tpm: Proxy driver for supporting multiple emulated TPMs
On 04/07/2016 08:35 AM, Jarkko Sakkinen wrote: On Tue, Mar 29, 2016 at 02:19:12PM -0400, 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. Signed-off-by: Stefan Berger CC: linux-kernel@vger.kernel.org CC: linux-...@vger.kernel.org CC: linux-...@vger.kernel.org Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Thanks. So I can post a v10 where I have to re-introduce the priv field but put it into the tpm_chip struct. Obviously it needs this field. I am not sure whether you'll let me take the Reviewed-by and Tested-by, though? Stefan
Re: [PATCH v9 2/4] tpm: Proxy driver for supporting multiple emulated TPMs
On Tue, Mar 29, 2016 at 02:19:12PM -0400, 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. > > Signed-off-by: Stefan Berger > CC: linux-kernel@vger.kernel.org > CC: linux-...@vger.kernel.org > CC: linux-...@vger.kernel.org Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen /Jarkko > --- > drivers/char/tpm/Kconfig | 10 + > drivers/char/tpm/Makefile | 1 + > drivers/char/tpm/tpm_vtpm_proxy.c | 574 > ++ > include/uapi/linux/Kbuild | 1 + > include/uapi/linux/vtpm_proxy.h | 36 +++ > 5 files changed, 622 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..81abc4b > --- /dev/null > +++ b/drivers/char/tpm/tpm_vtpm_proxy.c > @@ -0,0 +1,574 @@ > +/* > + * 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 */ > +}; > + > +/* all supported flags */ > +#define VTPM_PROXY_FLAGS_ALL (VTPM_PROXY_FLAG_TPM2) > + > +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(&proxy_dev->buf_lock); > + > + len = proxy_dev->req_len; > + > + if (count < len) { > + mutex_unlock(&proxy_dev->buf_lock); > + pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n", > + count, len); > + return -EIO; > + } > + > + rc = copy_to_user
[PATCH v9 2/4] 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 | 574 ++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/vtpm_proxy.h | 36 +++ 5 files changed, 622 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..81abc4b --- /dev/null +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -0,0 +1,574 @@ +/* + * 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 */ +}; + +/* all supported flags */ +#define VTPM_PROXY_FLAGS_ALL (VTPM_PROXY_FLAG_TPM2) + +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(&proxy_dev->buf_lock); + + len = proxy_dev->req_len; + + if (count < len) { + mutex_unlock(&proxy_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(&proxy_dev->buf_lock); + + if (rc) + return -EFAULT; + + return len; +} + +/** + * vtpm_proxy_fops_write - Write TPM responses