CVE-2024-26991
Severity CVSS v4.0:
Pending analysis
Type:
CWE-125
Out-of-bounds Read
Publication date:
01/05/2024
Last modified:
04/11/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
KVM: x86/mmu: x86: Don&#39;t overflow lpage_info when checking attributes<br />
<br />
Fix KVM_SET_MEMORY_ATTRIBUTES to not overflow lpage_info array and trigger<br />
KASAN splat, as seen in the private_mem_conversions_test selftest.<br />
<br />
When memory attributes are set on a GFN range, that range will have<br />
specific properties applied to the TDP. A huge page cannot be used when<br />
the attributes are inconsistent, so they are disabled for those the<br />
specific huge pages. For internal KVM reasons, huge pages are also not<br />
allowed to span adjacent memslots regardless of whether the backing memory<br />
could be mapped as huge.<br />
<br />
What GFNs support which huge page sizes is tracked by an array of arrays<br />
&#39;lpage_info&#39; on the memslot, of ‘kvm_lpage_info’ structs. Each index of<br />
lpage_info contains a vmalloc allocated array of these for a specific<br />
supported page size. The kvm_lpage_info denotes whether a specific huge<br />
page (GFN and page size) on the memslot is supported. These arrays include<br />
indices for unaligned head and tail huge pages.<br />
<br />
Preventing huge pages from spanning adjacent memslot is covered by<br />
incrementing the count in head and tail kvm_lpage_info when the memslot is<br />
allocated, but disallowing huge pages for memory that has mixed attributes<br />
has to be done in a more complicated way. During the<br />
KVM_SET_MEMORY_ATTRIBUTES ioctl KVM updates lpage_info for each memslot in<br />
the range that has mismatched attributes. KVM does this a memslot at a<br />
time, and marks a special bit, KVM_LPAGE_MIXED_FLAG, in the kvm_lpage_info<br />
for any huge page. This bit is essentially a permanently elevated count.<br />
So huge pages will not be mapped for the GFN at that page size if the<br />
count is elevated in either case: a huge head or tail page unaligned to<br />
the memslot or if KVM_LPAGE_MIXED_FLAG is set because it has mixed<br />
attributes.<br />
<br />
To determine whether a huge page has consistent attributes, the<br />
KVM_SET_MEMORY_ATTRIBUTES operation checks an xarray to make sure it<br />
consistently has the incoming attribute. Since level - 1 huge pages are<br />
aligned to level huge pages, it employs an optimization. As long as the<br />
level - 1 huge pages are checked first, it can just check these and assume<br />
that if each level - 1 huge page contained within the level sized huge<br />
page is not mixed, then the level size huge page is not mixed. This<br />
optimization happens in the helper hugepage_has_attrs().<br />
<br />
Unfortunately, although the kvm_lpage_info array representing page size<br />
&#39;level&#39; will contain an entry for an unaligned tail page of size level,<br />
the array for level - 1 will not contain an entry for each GFN at page<br />
size level. The level - 1 array will only contain an index for any<br />
unaligned region covered by level - 1 huge page size, which can be a<br />
smaller region. So this causes the optimization to overflow the level - 1<br />
kvm_lpage_info and perform a vmalloc out of bounds read.<br />
<br />
In some cases of head and tail pages where an overflow could happen,<br />
callers skip the operation completely as KVM_LPAGE_MIXED_FLAG is not<br />
required to prevent huge pages as discussed earlier. But for memslots that<br />
are smaller than the 1GB page size, it does call hugepage_has_attrs(). In<br />
this case the huge page is both the head and tail page. The issue can be<br />
observed simply by compiling the kernel with CONFIG_KASAN_VMALLOC and<br />
running the selftest “private_mem_conversions_test”, which produces the<br />
output like the following:<br />
<br />
BUG: KASAN: vmalloc-out-of-bounds in hugepage_has_attrs+0x7e/0x110<br />
Read of size 4 at addr ffffc900000a3008 by task private_mem_con/169<br />
Call Trace:<br />
dump_stack_lvl<br />
print_report<br />
? __virt_addr_valid<br />
? hugepage_has_attrs<br />
? hugepage_has_attrs<br />
kasan_report<br />
? hugepage_has_attrs<br />
hugepage_has_attrs<br />
kvm_arch_post_set_memory_attributes<br />
kvm_vm_ioctl<br />
<br />
It is a little ambiguous whether the unaligned head page (in the bug case<br />
also the tail page) should be expected to have KVM_LPAGE_MIXED_FLAG set.<br />
It is not functionally required, as the unal<br />
---truncated---
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
| CPE | From | Up to |
|---|---|---|
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.8 (including) | 6.8.8 (excluding) |
| cpe:2.3:o:linux:linux_kernel:6.9:rc1:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.9:rc2:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.9:rc3:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.9:rc4:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/048cc4a028e635d339687ed968985d2d1669494c
- https://git.kernel.org/stable/c/992b54bd083c5bee24ff7cc35991388ab08598c4
- https://git.kernel.org/stable/c/048cc4a028e635d339687ed968985d2d1669494c
- https://git.kernel.org/stable/c/992b54bd083c5bee24ff7cc35991388ab08598c4
- https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/4EZ6PJW7VOZ224TD7N4JZNU6KV32ZJ53/
- https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/DAMSOZXJEPUOXW33WZYWCVAY7Z5S7OOY/
- https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/GCBZZEC7L7KTWWAS2NLJK6SO3IZIL4WW/



