]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
kvm: vmx: fix limit checking in get_vmx_mem_address()
authorEugene Korenevsky <ekorenevsky@gmail.com>
Wed, 5 Jun 2019 21:17:39 +0000 (00:17 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2019 05:24:41 +0000 (07:24 +0200)
[ Upstream commit c1a9acbc5295e278d788e9f7510f543bc9864fa2 ]

Intel SDM vol. 3, 5.3:
The processor causes a
general-protection exception (or, if the segment is SS, a stack-fault
exception) any time an attempt is made to access the following addresses
in a segment:
- A byte at an offset greater than the effective limit
- A word at an offset greater than the (effective-limit â€“ 1)
- A doubleword at an offset greater than the (effective-limit â€“ 3)
- A quadword at an offset greater than the (effective-limit â€“ 7)

Therefore, the generic limit checking error condition must be

exn = (off > limit + 1 - access_len) = (off + access_len - 1 > limit)

but not

exn = (off + access_len > limit)

as for now.

Also avoid integer overflow of `off` at 32-bit KVM by casting it to u64.

Note: access length is currently sizeof(u64) which is incorrect. This
will be fixed in the subsequent patch.

Signed-off-by: Eugene Korenevsky <ekorenevsky@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/kvm/vmx/nested.c

index b101127e13b6d369da4dc561374f4c04714f38ba..543d7d82479b9ba184cf53c70a0d2fdc5d604fd9 100644 (file)
@@ -4120,7 +4120,7 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
                 */
                if (!(s.base == 0 && s.limit == 0xffffffff &&
                     ((s.type & 8) || !(s.type & 4))))
-                       exn = exn || (off + sizeof(u64) > s.limit);
+                       exn = exn || ((u64)off + sizeof(u64) - 1 > s.limit);
        }
        if (exn) {
                kvm_queue_exception_e(vcpu,