CVE-2024-45025

Severity CVSS v4.0:
Pending analysis
Type:
CWE-787 Out-of-bounds Write
Publication date:
11/09/2024
Last modified:
19/06/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE<br /> <br /> copy_fd_bitmaps(new, old, count) is expected to copy the first<br /> count/BITS_PER_LONG bits from old-&gt;full_fds_bits[] and fill<br /> the rest with zeroes. What it does is copying enough words<br /> (BITS_TO_LONGS(count/BITS_PER_LONG)), then memsets the rest.<br /> That works fine, *if* all bits past the cutoff point are<br /> clear. Otherwise we are risking garbage from the last word<br /> we&amp;#39;d copied.<br /> <br /> For most of the callers that is true - expand_fdtable() has<br /> count equal to old-&gt;max_fds, so there&amp;#39;s no open descriptors<br /> past count, let alone fully occupied words in -&gt;open_fds[],<br /> which is what bits in -&gt;full_fds_bits[] correspond to.<br /> <br /> The other caller (dup_fd()) passes sane_fdtable_size(old_fdt, max_fds),<br /> which is the smallest multiple of BITS_PER_LONG that covers all<br /> opened descriptors below max_fds. In the common case (copying on<br /> fork()) max_fds is ~0U, so all opened descriptors will be below<br /> it and we are fine, by the same reasons why the call in expand_fdtable()<br /> is safe.<br /> <br /> Unfortunately, there is a case where max_fds is less than that<br /> and where we might, indeed, end up with junk in -&gt;full_fds_bits[] -<br /> close_range(from, to, CLOSE_RANGE_UNSHARE) with<br /> * descriptor table being currently shared<br /> * &amp;#39;to&amp;#39; being above the current capacity of descriptor table<br /> * &amp;#39;from&amp;#39; being just under some chunk of opened descriptors.<br /> In that case we end up with observably wrong behaviour - e.g. spawn<br /> a child with CLONE_FILES, get all descriptors in range 0..127 open,<br /> then close_range(64, ~0U, CLOSE_RANGE_UNSHARE) and watch dup(0) ending<br /> up with descriptor #128, despite #64 being observably not open.<br /> <br /> The minimally invasive fix would be to deal with that in dup_fd().<br /> If this proves to add measurable overhead, we can go that way, but<br /> let&amp;#39;s try to fix copy_fd_bitmaps() first.<br /> <br /> * new helper: bitmap_copy_and_expand(to, from, bits_to_copy, size).<br /> * make copy_fd_bitmaps() take the bitmap size in words, rather than<br /> bits; it&amp;#39;s &amp;#39;count&amp;#39; argument is always a multiple of BITS_PER_LONG,<br /> so we are not losing any information, and that way we can use the<br /> same helper for all three bitmaps - compiler will see that count<br /> is a multiple of BITS_PER_LONG for the large ones, so it&amp;#39;ll generate<br /> plain memcpy()+memset().<br /> <br /> Reproducer added to tools/testing/selftests/core/close_range_test.c

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.19.321 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.20 (including) 5.4.283 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.5 (including) 5.10.225 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.15.166 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.16 (including) 6.1.107 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.2 (including) 6.6.48 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.7 (including) 6.10.7 (excluding)
cpe:2.3:o:linux:linux_kernel:6.11:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.11:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.11:rc3:*:*:*:*:*:*