2021-04-13 17:51:26

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 00/22] KVM: x86: hyper-v: Fine-grained access check to Hyper-V hypercalls and MSRs

Currently, all implemented Hyper-V features (MSRs and hypercalls) are
available unconditionally to all Hyper-V enabled guests. This is not
ideal as KVM userspace may decide to provide only a subset of the
currently implemented features to emulate an older Hyper-V version,
to reduce attack surface,... Implement checks against guest visible
CPUIDs for all currently implemented MSRs and hypercalls.

RFC part:
- KVM has KVM_CAP_ENFORCE_PV_FEATURE_CPUID for KVM PV features. Should
we use it for Hyper-V as well or should we rather add a Hyper-V specific
CAP (or neither)?

TODO:
- Write a selftest
- Check with various Windows/Hyper-V versions that CPUID feature bits
are actually respected.

Vitaly Kuznetsov (22):
asm-generic/hyperv: add HV_STATUS_ACCESS_DENIED definition
KVM: x86: hyper-v: Cache guest CPUID leaves determining features
availability
KVM: x86: hyper-v: Honor HV_MSR_VP_RUNTIME_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_TIME_REF_COUNT_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_HYPERCALL_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_VP_INDEX_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_RESET_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_REFERENCE_TSC_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_SYNIC_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_SYNTIMER_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_MSR_APIC_ACCESS_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_ACCESS_FREQUENCY_MSRS privilege bit
KVM: x86: hyper-v: Honor HV_ACCESS_REENLIGHTENMENT privilege bit
KVM: x86: hyper-v: Honor HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
privilege bit
KVM: x86: hyper-v: Honor HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
privilege bit
KVM: x86: hyper-v: Honor HV_STIMER_DIRECT_MODE_AVAILABLE privilege bit
KVM: x86: hyper-v: Honor HV_POST_MESSAGES privilege bit
KVM: x86: hyper-v: Honor HV_SIGNAL_EVENTS privilege bit
KVM: x86: hyper-v: Honor HV_DEBUGGING privilege bit
KVM: x86: hyper-v: Honor HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED bit
KVM: x86: hyper-v: Honor HV_X64_CLUSTER_IPI_RECOMMENDED bit
KVM: x86: hyper-v: Check access to HVCALL_NOTIFY_LONG_SPIN_WAIT
hypercall

arch/x86/include/asm/kvm_host.h | 8 +
arch/x86/kvm/hyperv.c | 305 +++++++++++++++++++++++++++---
include/asm-generic/hyperv-tlfs.h | 1 +
3 files changed, 291 insertions(+), 23 deletions(-)

--
2.30.2


2021-04-13 17:51:30

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 03/22] KVM: x86: hyper-v: Honor HV_MSR_VP_RUNTIME_AVAILABLE privilege bit

HV_X64_MSR_VP_RUNTIME is only available to guest when
HV_MSR_VP_RUNTIME_AVAILABLE bit is exposed.

Note, writing to HV_X64_MSR_VP_RUNTIME is only available from the host so
kvm_hv_set_msr() doesn't need an additional check.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 781f9da9a418..b39445aabbc2 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1504,6 +1504,10 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata,
data = hv_vcpu->hv_vapic;
break;
case HV_X64_MSR_VP_RUNTIME:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_VP_RUNTIME_AVAILABLE)))
+ return 1;
+
data = current_task_runtime_100ns() + hv_vcpu->runtime_offset;
break;
case HV_X64_MSR_SCONTROL:
--
2.30.2

2021-04-13 17:51:33

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 07/22] KVM: x86: hyper-v: Honor HV_MSR_RESET_AVAILABLE privilege bit

HV_X64_MSR_RESET is only available to guest when HV_MSR_RESET_AVAILABLE bit
is exposed.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 07f1fc8575e5..15d557ce32b5 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1289,6 +1289,10 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
}
break;
case HV_X64_MSR_RESET:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_RESET_AVAILABLE)))
+ return 1;
+
if (data == 1) {
vcpu_debug(vcpu, "hyper-v reset requested\n");
kvm_make_request(KVM_REQ_HV_RESET, vcpu);
@@ -1483,6 +1487,10 @@ static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata,
case HV_X64_MSR_CRASH_CTL:
return kvm_hv_msr_get_crash_ctl(kvm, pdata);
case HV_X64_MSR_RESET:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_RESET_AVAILABLE)))
+ return 1;
+
data = 0;
break;
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
--
2.30.2

2021-04-13 17:51:47

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 15/22] KVM: x86: hyper-v: Honor HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE privilege bit

Synthetic debugging MSRs (HV_X64_MSR_SYNDBG_CONTROL,
HV_X64_MSR_SYNDBG_STATUS, HV_X64_MSR_SYNDBG_SEND_BUFFER,
HV_X64_MSR_SYNDBG_RECV_BUFFER, HV_X64_MSR_SYNDBG_PENDING_BUFFER,
HV_X64_MSR_SYNDBG_OPTIONS) are only available to guest when
HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE bit is exposed.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 0678f1012ed7..1299847c89ba 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -312,7 +312,9 @@ static int syndbg_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
{
struct kvm_hv_syndbg *syndbg = to_hv_syndbg(vcpu);

- if (!kvm_hv_is_syndbg_enabled(vcpu) && !host)
+ if (unlikely(!host && (!kvm_hv_is_syndbg_enabled(vcpu) ||
+ !(to_hv_vcpu(vcpu)->cpuid_cache.features_edx &
+ HV_FEATURE_DEBUG_MSRS_AVAILABLE))))
return 1;

trace_kvm_hv_syndbg_set_msr(vcpu->vcpu_id,
@@ -351,7 +353,9 @@ static int syndbg_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host)
{
struct kvm_hv_syndbg *syndbg = to_hv_syndbg(vcpu);

- if (!kvm_hv_is_syndbg_enabled(vcpu) && !host)
+ if (unlikely(!host && (!kvm_hv_is_syndbg_enabled(vcpu) ||
+ !(to_hv_vcpu(vcpu)->cpuid_cache.features_edx &
+ HV_FEATURE_DEBUG_MSRS_AVAILABLE))))
return 1;

switch (msr) {
--
2.30.2

2021-04-13 17:51:47

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 17/22] KVM: x86: hyper-v: Honor HV_POST_MESSAGES privilege bit

Hyper-V partition must possess 'HV_POST_MESSAGES' privilege to issue
HVCALL_POST_MESSAGE hypercalls.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 0df18187d908..6e4bf1da9dcf 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2073,12 +2073,16 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS;
uint16_t code, rep_idx, rep_cnt;
bool fast, rep;
+ struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);

/*
* hypercall generates UD from non zero cpl and real mode
- * per HYPER-V spec
+ * per HYPER-V spec. Fail the call when 'hv_vcpu' context
+ * was not allocated (e.g. per-vCPU Hyper-V CPUID entries
+ * are unset) as well.
*/
- if (static_call(kvm_x86_get_cpl)(vcpu) != 0 || !is_protmode(vcpu)) {
+ if (static_call(kvm_x86_get_cpl)(vcpu) != 0 || !is_protmode(vcpu) ||
+ !hv_vcpu) {
kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
@@ -2125,6 +2129,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
break;
fallthrough; /* maybe userspace knows this conn_id */
case HVCALL_POST_MESSAGE:
+ if (unlikely(!(hv_vcpu->cpuid_cache.features_ebx &
+ HV_POST_MESSAGES))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
/* don't bother userspace if it has no way to handle it */
if (unlikely(rep || !to_hv_synic(vcpu)->active)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
--
2.30.2

2021-04-13 17:51:48

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 18/22] KVM: x86: hyper-v: Honor HV_SIGNAL_EVENTS privilege bit

Hyper-V partition must possess 'HV_SIGNAL_EVENTS' privilege to issue
HVCALL_SIGNAL_EVENT hypercalls.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 6e4bf1da9dcf..b661f92d90c8 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2120,6 +2120,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
kvm_vcpu_on_spin(vcpu, true);
break;
case HVCALL_SIGNAL_EVENT:
+ if (unlikely(!(hv_vcpu->cpuid_cache.features_ebx &
+ HV_SIGNAL_EVENTS))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
--
2.30.2

2021-04-13 17:51:49

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 20/22] KVM: x86: hyper-v: Honor HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED bit

Hyper-V partition must possess 'HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED'
privilege ('recommended' is rather a misnomer) to issue
HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST/SPACE hypercalls. '_EX' versions of these
hypercalls also require HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 7cb1dd1a9fc1..3e8a34c08aef 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2155,6 +2155,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
kvm_hv_hypercall_complete_userspace;
return 0;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(fast || !rep_cnt || rep_idx)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
@@ -2162,6 +2168,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false);
break;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(fast || rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
@@ -2169,6 +2181,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false);
break;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) ||
+ !(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(fast || !rep_cnt || rep_idx)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
@@ -2176,6 +2196,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true);
break;
case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED) ||
+ !(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(fast || rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
--
2.30.2

2021-04-13 17:51:51

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 01/22] asm-generic/hyperv: add HV_STATUS_ACCESS_DENIED definition

From TLFSv6.0b, this status means: "The caller did not possess sufficient
access rights to perform the requested operation."

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
include/asm-generic/hyperv-tlfs.h | 1 +
1 file changed, 1 insertion(+)

diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
index 83448e837ded..e01a3bade13a 100644
--- a/include/asm-generic/hyperv-tlfs.h
+++ b/include/asm-generic/hyperv-tlfs.h
@@ -187,6 +187,7 @@ enum HV_GENERIC_SET_FORMAT {
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INVALID_PARAMETER 5
+#define HV_STATUS_ACCESS_DENIED 6
#define HV_STATUS_OPERATION_DENIED 8
#define HV_STATUS_INSUFFICIENT_MEMORY 11
#define HV_STATUS_INVALID_PORT_ID 17
--
2.30.2

2021-04-13 17:51:54

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 22/22] KVM: x86: hyper-v: Check access to HVCALL_NOTIFY_LONG_SPIN_WAIT hypercall

TLFS6.0b states that partition issuing HVCALL_NOTIFY_LONG_SPIN_WAIT must
posess 'UseHypercallForLongSpinWait' privilege but there's no
corresponding feature bit. Instead, we have "Recommended number of attempts
to retry a spinlock failure before notifying the hypervisor about the
failures. 0xFFFFFFFF indicates never notify." Use this to check access to
the hypercall. Also, check against zero as the corresponding CPUID must
be set (and '0' attempts before re-try is weird anyway).

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 37b8ff30fc1d..325446833bbe 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2113,6 +2113,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)

switch (code) {
case HVCALL_NOTIFY_LONG_SPIN_WAIT:
+ if (unlikely(!hv_vcpu->cpuid_cache.enlightenments_ebx ||
+ hv_vcpu->cpuid_cache.enlightenments_ebx == U32_MAX)) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
--
2.30.2

2021-04-13 17:51:56

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 06/22] KVM: x86: hyper-v: Honor HV_MSR_VP_INDEX_AVAILABLE privilege bit

HV_X64_MSR_VP_INDEX is only available to guest when
HV_MSR_VP_INDEX_AVAILABLE bit is exposed.

Note, writing to HV_X64_MSR_VP_INDEX is only available from the host so
kvm_hv_set_msr() doesn't need an additional check.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 7fdd9b9c50d6..07f1fc8575e5 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1514,6 +1514,10 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata,

switch (msr) {
case HV_X64_MSR_VP_INDEX:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_VP_INDEX_AVAILABLE)))
+ return 1;
+
data = hv_vcpu->vp_index;
break;
case HV_X64_MSR_EOI:
--
2.30.2

2021-04-13 17:52:47

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 21/22] KVM: x86: hyper-v: Honor HV_X64_CLUSTER_IPI_RECOMMENDED bit

Hyper-V partition must possess 'HV_X64_CLUSTER_IPI_RECOMMENDED'
privilege ('recommended' is rather a misnomer) to issue
HVCALL_SEND_IPI hypercalls. 'HVCALL_SEND_IPI_EX' version of the
hypercall also requires HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 3e8a34c08aef..37b8ff30fc1d 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2211,6 +2211,12 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true);
break;
case HVCALL_SEND_IPI:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_CLUSTER_IPI_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
@@ -2218,6 +2224,14 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
ret = kvm_hv_send_ipi(vcpu, ingpa, outgpa, false, fast);
break;
case HVCALL_SEND_IPI_EX:
+ if (unlikely(!(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_CLUSTER_IPI_RECOMMENDED) ||
+ !(hv_vcpu->cpuid_cache.enlightenments_eax &
+ HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))) {
+ ret = HV_STATUS_ACCESS_DENIED;
+ break;
+ }
+
if (unlikely(fast || rep)) {
ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
--
2.30.2

2021-04-13 17:52:58

by Vitaly Kuznetsov

[permalink] [raw]
Subject: [PATCH RFC 11/22] KVM: x86: hyper-v: Honor HV_MSR_APIC_ACCESS_AVAILABLE privilege bit

HV_X64_MSR_EOI, HV_X64_MSR_ICR, HV_X64_MSR_TPR, and
HV_X64_MSR_VP_ASSIST_PAGE are only available to guest when
HV_MSR_APIC_ACCESS_AVAILABLE bit is exposed.

Signed-off-by: Vitaly Kuznetsov <[email protected]>
---
arch/x86/kvm/hyperv.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 032305ad5615..9c4454873e00 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1401,6 +1401,10 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
u64 gfn;
unsigned long addr;

+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
if (!(data & HV_X64_MSR_VP_ASSIST_PAGE_ENABLE)) {
hv_vcpu->hv_vapic = data;
if (kvm_lapic_enable_pv_eoi(vcpu, 0, 0))
@@ -1428,10 +1432,22 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
break;
}
case HV_X64_MSR_EOI:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
case HV_X64_MSR_ICR:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
case HV_X64_MSR_TPR:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
case HV_X64_MSR_VP_RUNTIME:
if (!host)
@@ -1564,12 +1580,28 @@ static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata,
data = hv_vcpu->vp_index;
break;
case HV_X64_MSR_EOI:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
case HV_X64_MSR_ICR:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
case HV_X64_MSR_TPR:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
case HV_X64_MSR_VP_ASSIST_PAGE:
+ if (unlikely(!host && !(hv_vcpu->cpuid_cache.features_eax &
+ HV_MSR_APIC_ACCESS_AVAILABLE)))
+ return 1;
+
data = hv_vcpu->hv_vapic;
break;
case HV_X64_MSR_VP_RUNTIME:
--
2.30.2

2021-04-15 14:16:19

by Wei Liu

[permalink] [raw]
Subject: Re: [PATCH RFC 01/22] asm-generic/hyperv: add HV_STATUS_ACCESS_DENIED definition

On Tue, Apr 13, 2021 at 02:26:09PM +0200, Vitaly Kuznetsov wrote:
> From TLFSv6.0b, this status means: "The caller did not possess sufficient
> access rights to perform the requested operation."
>
> Signed-off-by: Vitaly Kuznetsov <[email protected]>

This can be applied to hyperv-next right away. Let me know what you
think.

Wei.

> ---
> include/asm-generic/hyperv-tlfs.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
> index 83448e837ded..e01a3bade13a 100644
> --- a/include/asm-generic/hyperv-tlfs.h
> +++ b/include/asm-generic/hyperv-tlfs.h
> @@ -187,6 +187,7 @@ enum HV_GENERIC_SET_FORMAT {
> #define HV_STATUS_INVALID_HYPERCALL_INPUT 3
> #define HV_STATUS_INVALID_ALIGNMENT 4
> #define HV_STATUS_INVALID_PARAMETER 5
> +#define HV_STATUS_ACCESS_DENIED 6
> #define HV_STATUS_OPERATION_DENIED 8
> #define HV_STATUS_INSUFFICIENT_MEMORY 11
> #define HV_STATUS_INVALID_PORT_ID 17
> --
> 2.30.2
>

2021-04-15 15:34:11

by Vitaly Kuznetsov

[permalink] [raw]
Subject: Re: [PATCH RFC 01/22] asm-generic/hyperv: add HV_STATUS_ACCESS_DENIED definition

Wei Liu <[email protected]> writes:

> On Tue, Apr 13, 2021 at 02:26:09PM +0200, Vitaly Kuznetsov wrote:
>> From TLFSv6.0b, this status means: "The caller did not possess sufficient
>> access rights to perform the requested operation."
>>
>> Signed-off-by: Vitaly Kuznetsov <[email protected]>
>
> This can be applied to hyperv-next right away. Let me know what you
> think.
>

In case there's no immediate need for this constant outside of KVM, I'd
suggest you just give Paolo your 'Acked-by' so I can carry the patch in
the series for the time being. This will eliminate the need to track
dependencies between hyperv-next and kvm-next.

Thanks!

--
Vitaly

2021-04-16 12:06:14

by Wei Liu

[permalink] [raw]
Subject: Re: [PATCH RFC 01/22] asm-generic/hyperv: add HV_STATUS_ACCESS_DENIED definition

On Thu, Apr 15, 2021 at 05:33:17PM +0200, Vitaly Kuznetsov wrote:
> Wei Liu <[email protected]> writes:
>
> > On Tue, Apr 13, 2021 at 02:26:09PM +0200, Vitaly Kuznetsov wrote:
> >> From TLFSv6.0b, this status means: "The caller did not possess sufficient
> >> access rights to perform the requested operation."
> >>
> >> Signed-off-by: Vitaly Kuznetsov <[email protected]>
> >
> > This can be applied to hyperv-next right away. Let me know what you
> > think.
> >
>
> In case there's no immediate need for this constant outside of KVM, I'd
> suggest you just give Paolo your 'Acked-by' so I can carry the patch in
> the series for the time being. This will eliminate the need to track
> dependencies between hyperv-next and kvm-next.

Acked-by: Wei Liu <[email protected]>