Re: [PATCH] crypto: ccp: introduce SEV_GET_ID2 command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm a little concerned that this immediately disables SEV_GET_ID.
IMHO, we should continue to support both for a period of time. One
justification for immediate disablement would be that if keeping it
around is likely to enabled incorrect or insecure userspace behavior
with a firmware change. Given that this value is passed directly to
the AMD server, I don't think either of these is the case and it can
probably be worked around on the server side.

On Wed, Feb 13, 2019 at 1:24 PM Singh, Brijesh <brijesh.singh@xxxxxxx> wrote:
>
> The current definition and implementation of the SEV_GET_ID command
> does not provide the length of the unique ID returned by the firmware.
> As per the firmware specification, the firmware may return an ID
> length that is not restricted to 64 bytes as assumed by the SEV_GET_ID
> command.
>
> Introduce the SEV_GET_ID2 command to allow for querying and returing
> the length of the ID. Deprecate the SEV_GET_ID in the favor of
> SEV_GET_ID2.
>
> Cc: Janakarajan Natarajan <Janakarajan.Natarajan@xxxxxxx>
> Cc: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
> Cc: Gary Hook <gary.hook@xxxxxxx>
> Cc: Tom Lendacky <thomas.lendacky@xxxxxxx>
> Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx>
> ---
>  drivers/crypto/ccp/psp-dev.c | 65 +++++++++++++++++++++++++-----------
>  include/uapi/linux/psp-sev.h | 18 +++++++---
>  2 files changed, 60 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
> index b16be8a11d92..b510900a9a83 100644
> --- a/drivers/crypto/ccp/psp-dev.c
> +++ b/drivers/crypto/ccp/psp-dev.c
> @@ -584,40 +584,63 @@ static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
>
>  static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp)
>  {
> +       struct sev_user_data_get_id2 input;
>         struct sev_data_get_id *data;
> -       u64 data_size, user_size;
> -       void *id_blob, *mem;
> +       void *id_blob = NULL;
>         int ret;
>
> -       /* SEV GET_ID available from SEV API v0.16 and up */
> +       /* SEV GET_ID is available from SEV API v0.16 and up */
>         if (!SEV_VERSION_GREATER_OR_EQUAL(0, 16))
>                 return -ENOTSUPP;
>
> -       /* SEV FW expects the buffer it fills with the ID to be
> -        * 8-byte aligned. Memory allocated should be enough to
> -        * hold data structure + alignment padding + memory
> -        * where SEV FW writes the ID.
> -        */
> -       data_size = ALIGN(sizeof(struct sev_data_get_id), 8);
> -       user_size = sizeof(struct sev_user_data_get_id);
> +       if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
> +               return -EFAULT;
>
> -       mem = kzalloc(data_size + user_size, GFP_KERNEL);
> -       if (!mem)
> +       /* Check if we have write access to the userspace buffer */
> +       if (input.address &&
> +           input.length &&
> +           !access_ok(input.address, input.length))
> +               return -EFAULT;
> +
> +       data = kzalloc(sizeof(*data), GFP_KERNEL);
> +       if (!data)
>                 return -ENOMEM;
>
> -       data = mem;
> -       id_blob = mem + data_size;
> +       if (input.address && input.length) {
> +               id_blob = kmalloc(input.length, GFP_KERNEL);
> +               if (!id_blob) {
> +                       kfree(data);
> +                       return -ENOMEM;
> +               }
>
> -       data->address = __psp_pa(id_blob);
> -       data->len = user_size;
> +               data->address = __psp_pa(id_blob);
> +               data->len = input.length;
> +       }
>
>         ret = __sev_do_cmd_locked(SEV_CMD_GET_ID, data, &argp->error);
> -       if (!ret) {
> -               if (copy_to_user((void __user *)argp->data, id_blob, data->len))
> +
> +       /*
> +        * Firmware will return the length of the ID value (either the minimum
> +        * required length or the actual length written), return it to the user.
> +        */
> +       input.length = data->len;
> +
> +       if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) {
> +               ret = -EFAULT;
> +               goto e_free;
> +       }
> +
> +       if (id_blob) {
> +               if (copy_to_user((void __user *)input.address,
> +                                id_blob, data->len)) {
>                         ret = -EFAULT;
> +                       goto e_free;
> +               }
>         }
>
> -       kfree(mem);
> +e_free:
> +       kfree(id_blob);
> +       kfree(data);
>
>         return ret;
>  }
> @@ -760,6 +783,10 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
>                 ret = sev_ioctl_do_pdh_export(&input);
>                 break;
>         case SEV_GET_ID:
> +               /* SEV_GET_ID is deprecated */
> +               ret = -ENOTSUPP;
> +               break;
> +       case SEV_GET_ID2:
>                 ret = sev_ioctl_do_get_id(&input);
>                 break;
>         default:
> diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h
> index ac8c60bcc83b..43521d500c2b 100644
> --- a/include/uapi/linux/psp-sev.h
> +++ b/include/uapi/linux/psp-sev.h
> @@ -6,8 +6,7 @@
>   *
>   * Author: Brijesh Singh <brijesh.singh@xxxxxxx>
>   *
> - * SEV spec 0.14 is available at:
> - * http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
> + * SEV API specification is available at: https://developer.amd.com/sev/
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -30,7 +29,8 @@ enum {
>         SEV_PDH_GEN,
>         SEV_PDH_CERT_EXPORT,
>         SEV_PEK_CERT_IMPORT,
> -       SEV_GET_ID,
> +       SEV_GET_ID,     /* This command is deprecated, use SEV_GET_ID2 */
> +       SEV_GET_ID2,
>
>         SEV_MAX,
>  };
> @@ -125,7 +125,7 @@ struct sev_user_data_pdh_cert_export {
>  } __packed;
>
>  /**
> - * struct sev_user_data_get_id - GET_ID command parameters
> + * struct sev_user_data_get_id - GET_ID command parameters (deprecated)
>   *
>   * @socket1: Buffer to pass unique ID of first socket
>   * @socket2: Buffer to pass unique ID of second socket
> @@ -135,6 +135,16 @@ struct sev_user_data_get_id {
>         __u8 socket2[64];                       /* Out */
>  } __packed;
>
> +/**
> + * struct sev_user_data_get_id2 - GET_ID command parameters
> + * @address: Buffer to store unique ID
> + * @length: length of the unique ID
> + */
> +struct sev_user_data_get_id2 {
> +       __u64 address;                          /* In */
> +       __u32 length;                           /* In/Out */
> +} __packed;
> +
>  /**
>   * struct sev_issue_cmd - SEV ioctl parameters
>   *
> --
> 2.17.1
>



[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux