qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [RFC PATCH v1 01/10] KVM: SVM: Add KVM_SEV SEND_START c


From: Borislav Petkov
Subject: Re: [Qemu-devel] [RFC PATCH v1 01/10] KVM: SVM: Add KVM_SEV SEND_START command
Date: Fri, 26 Apr 2019 16:10:42 +0200
User-agent: Mutt/1.10.1 (2018-07-13)

On Wed, Apr 24, 2019 at 04:09:59PM +0000, Singh, Brijesh wrote:
> The command is used to create an outgoing SEV guest encryption context.
> 
> Cc: Thomas Gleixner <address@hidden>
> Cc: Ingo Molnar <address@hidden>
> Cc: "H. Peter Anvin" <address@hidden>
> Cc: Paolo Bonzini <address@hidden>
> Cc: "Radim Krčmář" <address@hidden>
> Cc: Joerg Roedel <address@hidden>
> Cc: Borislav Petkov <address@hidden>
> Cc: Tom Lendacky <address@hidden>
> Cc: address@hidden
> Cc: address@hidden
> Cc: address@hidden
> Signed-off-by: Brijesh Singh <address@hidden>
> ---
>  .../virtual/kvm/amd-memory-encryption.rst     |  24 +++++
>  arch/x86/kvm/svm.c                            | 101 ++++++++++++++++++
>  include/uapi/linux/kvm.h                      |  12 +++
>  3 files changed, 137 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst 
> b/Documentation/virtual/kvm/amd-memory-encryption.rst
> index 659bbc093b52..340ac4f87321 100644
> --- a/Documentation/virtual/kvm/amd-memory-encryption.rst
> +++ b/Documentation/virtual/kvm/amd-memory-encryption.rst
> @@ -238,6 +238,30 @@ Returns: 0 on success, -negative on error
>                  __u32 trans_len;
>          };
>  
> +10. KVM_SEV_SEND_START
> +----------------------
> +
> +The KVM_SEV_SEND_START command can be used by the hypervisor to create an
> +outgoing guest encryption context.
> +
> +Parameters (in): struct kvm_sev_send_start
> +
> +Returns: 0 on success, -negative on error
> +
> +::
> +        struct kvm_sev_send_start {
> +                __u32 policy;                 /* guest policy */
> +
> +                __u64 pdh_cert_uaddr;         /* platform Diffie-Hellman 
> certificate */
> +                __u32 pdh_cert_len;
> +
> +                __u64 plat_cert_uaddr;        /* platform certificate chain 
> */
> +                __u32 plat_cert_len;
> +
> +                __u64 amd_cert_uaddr;         /* AMD certificate */
> +                __u32 amd_cert_len;

        __u64 session_uaddr;
        __u32 session_len;

too, right?

> +        };
> +
>  References
>  ==========
>  
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 406b558abfef..4c2a225ba546 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -6955,6 +6955,104 @@ static int sev_launch_secret(struct kvm *kvm, struct 
> kvm_sev_cmd *argp)
>       return ret;
>  }
>  
> +static int sev_send_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
> +{
> +     struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
> +     void *amd_cert = NULL, *session_data = NULL;
> +     void *pdh_cert = NULL, *plat_cert = NULL;
> +     struct sev_data_send_start *data = NULL;
> +     struct kvm_sev_send_start params;
> +     int ret;
> +
> +     if (!sev_guest(kvm))
> +             return -ENOTTY;
> +
> +     if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
> +                             sizeof(struct kvm_sev_send_start)))
> +             return -EFAULT;
> +
> +     data = kzalloc(sizeof(*data), GFP_KERNEL);
> +     if (!data)
> +             return -ENOMEM;
> +
> +     /* userspace wants to query the session length */
> +     if (!params.session_len)
> +             goto cmd;
> +
> +     if (!params.pdh_cert_uaddr || !params.pdh_cert_len ||
> +         !params.session_uaddr)
> +             return -EINVAL;
> +
> +     /* copy the certificate blobs from userspace */
> +     pdh_cert = psp_copy_user_blob(params.pdh_cert_uaddr, 
> params.pdh_cert_len);
> +     if (IS_ERR(pdh_cert)) {
> +             ret = PTR_ERR(pdh_cert);
> +             goto e_free;
> +     }
> +
> +     data->pdh_cert_address = __psp_pa(pdh_cert);
> +     data->pdh_cert_len = params.pdh_cert_len;
> +
> +     plat_cert = psp_copy_user_blob(params.plat_cert_uaddr, 
> params.plat_cert_len);
> +     if (IS_ERR(plat_cert)) {
> +             ret = PTR_ERR(plat_cert);
> +             goto e_free_pdh;
> +     }
> +
> +     data->plat_cert_address = __psp_pa(plat_cert);
> +     data->plat_cert_len = params.plat_cert_len;
> +
> +     amd_cert = psp_copy_user_blob(params.amd_cert_uaddr, 
> params.amd_cert_len);
> +     if (IS_ERR(amd_cert)) {
> +             ret = PTR_ERR(amd_cert);
> +             goto e_free_plat_cert;
> +     }
> +
> +     data->amd_cert_address = __psp_pa(amd_cert);
> +     data->amd_cert_len = params.amd_cert_len;
> +
> +     ret = -ENOMEM;
> +     session_data = kmalloc(params.session_len, GFP_KERNEL);

If the user is supposed to query the session length first, you could
save it in a global variable perhaps and use that value instead of
trusting the user to give you the correct one in params.session_len for
the allocation...

> +     if (!session_data)
> +             goto e_free_amd_cert;
> +
> +     data->session_address = __psp_pa(session_data);
> +     data->session_len = params.session_len;
> +cmd:
> +     data->handle = sev->handle;
> +     ret = sev_issue_cmd(kvm, SEV_CMD_SEND_START, data, &argp->error);
> +
> +     /* if we queried the session length, FW responded with expected data */

<--- ... here you have the session length from the fw.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]