]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: selftests: Fix sign extension bug in get_desc64_base()
authorMJ Pooladkhay <mj@pooladkhay.com>
Mon, 22 Dec 2025 17:42:07 +0000 (17:42 +0000)
committerSean Christopherson <seanjc@google.com>
Thu, 8 Jan 2026 20:00:56 +0000 (12:00 -0800)
The function get_desc64_base() performs a series of bitwise left shifts on
fields of various sizes. More specifically, when performing '<< 24' on
'desc->base2' (which is a u8), 'base2' is promoted to a signed integer
before shifting.

In a scenario where base2 >= 0x80, the shift places a 1 into bit 31,
causing the 32-bit intermediate value to become negative. When this
result is cast to uint64_t or ORed into the return value, sign extension
occurs, corrupting the upper 32 bits of the address (base3).

Example:
Given:
  base0 = 0x5000
  base1 = 0xd6
  base2 = 0xf8
  base3 = 0xfffffe7c

Expected return: 0xfffffe7cf8d65000
Actual return:   0xfffffffff8d65000

Fix this by explicitly casting the fields to 'uint64_t' before shifting
to prevent sign extension.

Signed-off-by: MJ Pooladkhay <mj@pooladkhay.com>
Link: https://patch.msgid.link/20251222174207.107331-1-mj@pooladkhay.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/include/x86/processor.h

index 57d62a425109bb90324c39aedd60ddde68f516ce..26a91bb73c93a0701f0cb0be8a5d06cfab4c737a 100644 (file)
@@ -436,8 +436,10 @@ struct kvm_x86_state {
 
 static inline uint64_t get_desc64_base(const struct desc64 *desc)
 {
-       return ((uint64_t)desc->base3 << 32) |
-               (desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
+       return (uint64_t)desc->base3 << 32 |
+              (uint64_t)desc->base2 << 24 |
+              (uint64_t)desc->base1 << 16 |
+              (uint64_t)desc->base0;
 }
 
 static inline uint64_t rdtsc(void)