Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 75236f5

Browse files
sean-jcbonzini
authored andcommitted
KVM: SEV: Return appropriate error codes if SEV-ES scratch setup fails
Return appropriate error codes if setting up the GHCB scratch area for an SEV-ES guest fails. In particular, returning -EINVAL instead of -ENOMEM when allocating the kernel buffer could be confusing as userspace would likely suspect a guest issue. Fixes: 8f423a8 ("KVM: SVM: Support MMIO for an SEV-ES guest") Cc: Tom Lendacky <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent a955cad commit 75236f5

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,7 +2530,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu)
25302530
}
25312531

25322532
#define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE)
2533-
static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
2533+
static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25342534
{
25352535
struct vmcb_control_area *control = &svm->vmcb->control;
25362536
struct ghcb *ghcb = svm->sev_es.ghcb;
@@ -2541,14 +2541,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25412541
scratch_gpa_beg = ghcb_get_sw_scratch(ghcb);
25422542
if (!scratch_gpa_beg) {
25432543
pr_err("vmgexit: scratch gpa not provided\n");
2544-
return false;
2544+
return -EINVAL;
25452545
}
25462546

25472547
scratch_gpa_end = scratch_gpa_beg + len;
25482548
if (scratch_gpa_end < scratch_gpa_beg) {
25492549
pr_err("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n",
25502550
len, scratch_gpa_beg);
2551-
return false;
2551+
return -EINVAL;
25522552
}
25532553

25542554
if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) {
@@ -2566,7 +2566,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25662566
scratch_gpa_end > ghcb_scratch_end) {
25672567
pr_err("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n",
25682568
scratch_gpa_beg, scratch_gpa_end);
2569-
return false;
2569+
return -EINVAL;
25702570
}
25712571

25722572
scratch_va = (void *)svm->sev_es.ghcb;
@@ -2579,18 +2579,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25792579
if (len > GHCB_SCRATCH_AREA_LIMIT) {
25802580
pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n",
25812581
len, GHCB_SCRATCH_AREA_LIMIT);
2582-
return false;
2582+
return -EINVAL;
25832583
}
25842584
scratch_va = kzalloc(len, GFP_KERNEL_ACCOUNT);
25852585
if (!scratch_va)
2586-
return false;
2586+
return -ENOMEM;
25872587

25882588
if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, len)) {
25892589
/* Unable to copy scratch area from guest */
25902590
pr_err("vmgexit: kvm_read_guest for scratch area failed\n");
25912591

25922592
kfree(scratch_va);
2593-
return false;
2593+
return -EFAULT;
25942594
}
25952595

25962596
/*
@@ -2606,7 +2606,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
26062606
svm->sev_es.ghcb_sa = scratch_va;
26072607
svm->sev_es.ghcb_sa_len = len;
26082608

2609-
return true;
2609+
return 0;
26102610
}
26112611

26122612
static void set_ghcb_msr_bits(struct vcpu_svm *svm, u64 value, u64 mask,
@@ -2745,10 +2745,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27452745
ghcb_set_sw_exit_info_1(ghcb, 0);
27462746
ghcb_set_sw_exit_info_2(ghcb, 0);
27472747

2748-
ret = -EINVAL;
27492748
switch (exit_code) {
27502749
case SVM_VMGEXIT_MMIO_READ:
2751-
if (!setup_vmgexit_scratch(svm, true, control->exit_info_2))
2750+
ret = setup_vmgexit_scratch(svm, true, control->exit_info_2);
2751+
if (ret)
27522752
break;
27532753

27542754
ret = kvm_sev_es_mmio_read(vcpu,
@@ -2757,7 +2757,8 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27572757
svm->sev_es.ghcb_sa);
27582758
break;
27592759
case SVM_VMGEXIT_MMIO_WRITE:
2760-
if (!setup_vmgexit_scratch(svm, false, control->exit_info_2))
2760+
ret = setup_vmgexit_scratch(svm, false, control->exit_info_2);
2761+
if (ret)
27612762
break;
27622763

27632764
ret = kvm_sev_es_mmio_write(vcpu,
@@ -2800,6 +2801,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
28002801
vcpu_unimpl(vcpu,
28012802
"vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n",
28022803
control->exit_info_1, control->exit_info_2);
2804+
ret = -EINVAL;
28032805
break;
28042806
default:
28052807
ret = svm_invoke_exit_handler(vcpu, exit_code);
@@ -2812,6 +2814,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
28122814
{
28132815
int count;
28142816
int bytes;
2817+
int r;
28152818

28162819
if (svm->vmcb->control.exit_info_2 > INT_MAX)
28172820
return -EINVAL;
@@ -2820,8 +2823,9 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
28202823
if (unlikely(check_mul_overflow(count, size, &bytes)))
28212824
return -EINVAL;
28222825

2823-
if (!setup_vmgexit_scratch(svm, in, bytes))
2824-
return -EINVAL;
2826+
r = setup_vmgexit_scratch(svm, in, bytes);
2827+
if (r)
2828+
return r;
28252829

28262830
return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->sev_es.ghcb_sa,
28272831
count, in);

0 commit comments

Comments
 (0)