diff mbox

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

Message ID 20171014100847.w3mmelt4qbnbzpca@pd.tnic (mailing list archive)
State New, archived
Headers show

Commit Message

Borislav Petkov Oct. 14, 2017, 10:08 a.m. UTC
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 mbox

Patch

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__ */