Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote on 01/02/2017 08:22:10 AM:

>
> Added a ioctl for creating a TPM space. The space is isolated from the
> other users of the TPM. Only a process holding the file with the handle
> can access the objects and only objects that are created through that
> file handle can be accessed.
>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> ---

> diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
> index 912ad30..139638b 100644
> --- a/drivers/char/tpm/tpm-dev.c
> +++ b/drivers/char/tpm/tpm-dev.c
> @@ -19,6 +19,7 @@
>   */
>  #include <linux/slab.h>
>  #include <linux/uaccess.h>
> +#include <uapi/linux/tpm.h>
>  #include "tpm.h"
>  
>  struct file_priv {
> @@ -32,6 +33,8 @@ struct file_priv {
>     struct work_struct work;
>  
>     u8 data_buffer[TPM_BUFSIZE];
> +   struct tpm_space space;
> +   bool has_space;
>  };
>  
>  static void user_reader_timeout(unsigned long ptr)
> @@ -115,6 +118,7 @@ static ssize_t tpm_write(struct file *file,
> const char __user *buf,
>            size_t size, loff_t *off)
>  {
>     struct file_priv *priv = file->private_data;
> +   struct tpm_space *space = NULL;
>     size_t in_size = size;
>     ssize_t out_size;
>  
> @@ -130,6 +134,9 @@ static ssize_t tpm_write(struct file *file,
> const char __user *buf,
>  
>     mutex_lock(&priv->buffer_mutex);
>  
> +   if (priv->has_space)
> +      space = &priv->space;
> +
>     if (copy_from_user
>         (priv->data_buffer, (void __user *) buf, in_size)) {
>        mutex_unlock(&priv->buffer_mutex);
> @@ -144,7 +151,7 @@ static ssize_t tpm_write(struct file *file,
> const char __user *buf,
>        mutex_unlock(&priv->buffer_mutex);
>        return -EPIPE;
>     }
> -   out_size = tpm_transmit(priv->chip, priv->data_buffer,
> +   out_size = tpm_transmit(priv->chip, space, priv->data_buffer,
>              sizeof(priv->data_buffer), 0);
>  
>     tpm_put_ops(priv->chip);
> @@ -162,6 +169,65 @@ static ssize_t tpm_write(struct file *file,
> const char __user *buf,
>     return in_size;
>  }
>  
> +/**
> + * tpm_ioc_new_space - handler for %SGX_IOC_NEW_SPACE ioctl
> + *
> + * Creates a new TPM space that can hold a set of transient
> objects. The space
> + * is isolated with virtual handles that are mapped into physical
> handles by the
> + * driver.
> + */
> +static long tpm_ioc_new_space(struct file *file, unsigned int ioctl,
> +               unsigned long arg)
> +{
> +   struct file_priv *priv = file->private_data;
> +   struct tpm_chip *chip = priv->chip;
> +   int rc = 0;
> +
> +   if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
> +      return -EOPNOTSUPP;
> +
> +   mutex_lock(&priv->buffer_mutex);
> +
> +   if (priv->has_space) {
> +      rc = -EBUSY;
> +      goto out;
> +   }
> +
> +   priv->space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> +   if (!priv->space.context_buf) {
> +      rc = -ENOMEM;
> +      goto out;
> +   }
> +
> +   /* The TPM device can be opened again as this file has been moved to a
> +    * TPM handle space.
> +    */
> +   priv->has_space = true;
> +   clear_bit(0, &chip->is_open);
> +out:
> +   mutex_unlock(&priv->buffer_mutex);
> +   return rc;
> +}
> +
> +static long tpm_ioctl(struct file *file, unsigned int ioctl,
> +            unsigned long arg)
> +{
> +   switch (ioctl) {
> +   case TPM_IOC_NEW_SPACE:
> +      return tpm_ioc_new_space(file, ioctl, arg);
> +   default:
> +      return -ENOIOCTLCMD;
> +   }
> +}
> +
> +#ifdef CONFIG_COMPAT
> +static long tpm_compat_ioctl(struct file *file, unsigned int ioctl,
> +              unsigned long arg)
> +{
> +   return tpm_ioctl(file, ioctl, arg);
> +}
> +#endif
> +
>  /*
>   * Called on file close
>   */
> @@ -169,6 +235,14 @@ static int tpm_release(struct inode *inode,
> struct file *file)
>  {
>     struct file_priv *priv = file->private_data;
>  
> +   if (tpm_try_get_ops(priv->chip)) {
> +      mutex_unlock(&priv->buffer_mutex);
> +      return -EPIPE;
> +   }



That mutex_unlock looks wrong.

   Stefan