Re: [Part2 PATCH v5 19/31] KVM: SVM: Add support for KVM_SEV_LAUNCH_START command

From: Borislav Petkov
Date: Sat Oct 14 2017 - 06:09:02 EST


On Wed, Oct 04, 2017 at 08:14:00AM -0500, Brijesh Singh wrote:
> The KVM_SEV_LAUNCH_START command is used to create a memory encryption
> context within the SEV firmware. In order to create the memory encryption
> context, the guest owner's should provide the guest's policy, its public
> Diffie-Hellman (PDH) key and session information. The command implements
> the LAUNCH_START flow defined in SEV spec Section 6.2.

Minor cleanups:

"The KVM_SEV_LAUNCH_START command is used to create a memory encryption
context within the SEV firmware. In order to do so, the guest owner
should provide the guest's policy, its public Diffie-Hellman (PDH) key
and session information. The command implements the LAUNCH_START flow
defined in SEV spec Section 6.2."

Also, you can avoid the copy_user_blob() duplication by exporting the
version in psp-dev.c. Rest is minor cleanups.

---
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 55a4b7b9945c..a0106f31a5a7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -5713,31 +5713,6 @@ static int sev_issue_cmd(int fd, int id, void *data, int *error)
return ret;
}

-static void *copy_user_blob(u64 __user uaddr, u32 len)
-{
- void *data;
-
- if (!uaddr || !len)
- return ERR_PTR(-EINVAL);
-
- /* verify that blob length does not exceed our limit */
- if (len > SEV_FW_BLOB_MAX_SIZE)
- return ERR_PTR(-EINVAL);
-
- data = kmalloc(len, GFP_KERNEL);
- if (!data)
- return ERR_PTR(-ENOMEM);
-
- if (copy_from_user(data, (void __user *)(uintptr_t)uaddr, len))
- goto e_free;
-
- return data;
-
-e_free:
- kfree(data);
- return ERR_PTR(-EFAULT);
-}
-
static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
{
struct kvm_sev_info *sev = &kvm->arch.sev_info;
@@ -5750,8 +5725,7 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
if (!sev_guest(kvm))
return -ENOTTY;

- if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data,
- sizeof(struct kvm_sev_launch_start)))
+ if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data, sizeof(params)))
return -EFAULT;

start = kzalloc(sizeof(*start), GFP_KERNEL);
@@ -5760,7 +5734,7 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)

dh_blob = NULL;
if (params.dh_uaddr) {
- dh_blob = copy_user_blob(params.dh_uaddr, params.dh_len);
+ dh_blob = psp_copy_user_blob(params.dh_uaddr, params.dh_len);
if (IS_ERR(dh_blob)) {
ret = PTR_ERR(dh_blob);
goto e_free;
@@ -5772,7 +5746,7 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)

session_blob = NULL;
if (params.session_uaddr) {
- dh_blob = copy_user_blob(params.session_uaddr, params.session_len);
+ dh_blob = psp_copy_user_blob(params.session_uaddr, params.session_len);
if (IS_ERR(session_blob)) {
ret = PTR_ERR(session_blob);
goto e_free_dh;
@@ -5797,8 +5771,8 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)

/* return handle to userspace */
params.handle = start->handle;
- if (copy_to_user((void __user *)(uintptr_t)argp->data, &params,
- sizeof(struct kvm_sev_launch_start))) {
+ ret = copy_to_user((void __user *)(uintptr_t)argp->data, &params, sizeof(params));
+ if (ret) {
sev_unbind_asid(kvm, start->handle);
ret = -EFAULT;
goto e_free_session;
@@ -5834,10 +5808,9 @@ static int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
r = sev_guest_init(kvm, &sev_cmd);
break;

- case KVM_SEV_LAUNCH_START: {
+ case KVM_SEV_LAUNCH_START:
r = sev_launch_start(kvm, &sev_cmd);
break;
- }

default:
break;
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
index 331d028f9445..676abc233833 100644
--- a/drivers/crypto/ccp/psp-dev.c
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -377,7 +377,7 @@ static int sev_ioctl_pek_csr(struct sev_issue_cmd *argp)
return ret;
}

-static void *copy_user_blob(u64 __user uaddr, u32 len)
+void *psp_copy_user_blob(u64 __user uaddr, u32 len)
{
void *data;

@@ -392,7 +392,7 @@ static void *copy_user_blob(u64 __user uaddr, u32 len)
if (!data)
return ERR_PTR(-ENOMEM);

- if (copy_from_user(data, (void __user *)uaddr, len))
+ if (copy_from_user(data, (void __user *)(uintptr_t)uaddr, len))
goto e_free;

return data;
@@ -401,6 +401,7 @@ static void *copy_user_blob(u64 __user uaddr, u32 len)
kfree(data);
return ERR_PTR(-EFAULT);
}
+EXPORT_SYMBOL_GPL(psp_copy_user_blob);

static int sev_ioctl_pek_cert_import(struct sev_issue_cmd *argp)
{
@@ -417,7 +418,7 @@ static int sev_ioctl_pek_cert_import(struct sev_issue_cmd *argp)
return -ENOMEM;

/* copy PEK certificate blobs from userspace */
- pek_blob = copy_user_blob(input.pek_cert_address, input.pek_cert_len);
+ pek_blob = psp_copy_user_blob(input.pek_cert_address, input.pek_cert_len);
if (IS_ERR(pek_blob)) {
ret = PTR_ERR(pek_blob);
goto e_free;
@@ -427,7 +428,7 @@ static int sev_ioctl_pek_cert_import(struct sev_issue_cmd *argp)
data->pek_cert_len = input.pek_cert_len;

/* copy PEK certificate blobs from userspace */
- oca_blob = copy_user_blob(input.oca_cert_address, input.oca_cert_len);
+ oca_blob = psp_copy_user_blob(input.oca_cert_address, input.oca_cert_len);
if (IS_ERR(oca_blob)) {
ret = PTR_ERR(oca_blob);
goto e_free_pek;
diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
index 17cd13e2bbe4..1bfa4f3a71cc 100644
--- a/include/linux/psp-sev.h
+++ b/include/linux/psp-sev.h
@@ -638,6 +638,7 @@ int sev_guest_df_flush(int *error);
* -%EIO if the sev returned a non-zero return code
*/
int sev_guest_decommission(struct sev_data_decommission *data, int *error);
+void *psp_copy_user_blob(u64 __user uaddr, u32 len);

#else /* !CONFIG_CRYPTO_DEV_SP_PSP */

@@ -667,6 +668,8 @@ sev_issue_cmd_external_user(struct file *filep,
return -ENODEV;
}

+static inline void *psp_copy_user_blob(u64 __user uaddr, u32 len) { return ERR_PTR(-EINVAL); }
+
#endif /* CONFIG_CRYPTO_DEV_SP_PSP */

#endif /* __PSP_SEV_H__ */


--
Regards/Gruss,
Boris.

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