CVE-2021-47011
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
28/02/2024
Last modified:
08/01/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
mm: memcontrol: slab: fix obtain a reference to a freeing memcg<br />
<br />
Patch series "Use obj_cgroup APIs to charge kmem pages", v5.<br />
<br />
Since Roman&#39;s series "The new cgroup slab memory controller" applied.<br />
All slab objects are charged with the new APIs of obj_cgroup. The new<br />
APIs introduce a struct obj_cgroup to charge slab objects. It prevents<br />
long-living objects from pinning the original memory cgroup in the<br />
memory. But there are still some corner objects (e.g. allocations<br />
larger than order-1 page on SLUB) which are not charged with the new<br />
APIs. Those objects (include the pages which are allocated from buddy<br />
allocator directly) are charged as kmem pages which still hold a<br />
reference to the memory cgroup.<br />
<br />
E.g. We know that the kernel stack is charged as kmem pages because the<br />
size of the kernel stack can be greater than 2 pages (e.g. 16KB on<br />
x86_64 or arm64). If we create a thread (suppose the thread stack is<br />
charged to memory cgroup A) and then move it from memory cgroup A to<br />
memory cgroup B. Because the kernel stack of the thread hold a<br />
reference to the memory cgroup A. The thread can pin the memory cgroup<br />
A in the memory even if we remove the cgroup A. If we want to see this<br />
scenario by using the following script. We can see that the system has<br />
added 500 dying cgroups (This is not a real world issue, just a script<br />
to show that the large kmallocs are charged as kmem pages which can pin<br />
the memory cgroup in the memory).<br />
<br />
#!/bin/bash<br />
<br />
cat /proc/cgroups | grep memory<br />
<br />
cd /sys/fs/cgroup/memory<br />
echo 1 > memory.move_charge_at_immigrate<br />
<br />
for i in range{1..500}<br />
do<br />
mkdir kmem_test<br />
echo $$ > kmem_test/cgroup.procs<br />
sleep 3600 &<br />
echo $$ > cgroup.procs<br />
echo `cat kmem_test/cgroup.procs` > cgroup.procs<br />
rmdir kmem_test<br />
done<br />
<br />
cat /proc/cgroups | grep memory<br />
<br />
This patchset aims to make those kmem pages to drop the reference to<br />
memory cgroup by using the APIs of obj_cgroup. Finally, we can see that<br />
the number of the dying cgroups will not increase if we run the above test<br />
script.<br />
<br />
This patch (of 7):<br />
<br />
The rcu_read_lock/unlock only can guarantee that the memcg will not be<br />
freed, but it cannot guarantee the success of css_get (which is in the<br />
refill_stock when cached memcg changed) to memcg.<br />
<br />
rcu_read_lock()<br />
memcg = obj_cgroup_memcg(old)<br />
__memcg_kmem_uncharge(memcg)<br />
refill_stock(memcg)<br />
if (stock->cached != memcg)<br />
// css_get can change the ref counter from 0 back to 1.<br />
css_get(&memcg->css)<br />
rcu_read_unlock()<br />
<br />
This fix is very like the commit:<br />
<br />
eefbfa7fd678 ("mm: memcg/slab: fix use after free in obj_cgroup_charge")<br />
<br />
Fix this by holding a reference to the memcg which is passed to the<br />
__memcg_kmem_uncharge() before calling __memcg_kmem_uncharge().
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:*:*:*:*:*:*:*:* | 5.10.11 (including) | 5.10.37 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.11.21 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.12 (including) | 5.12.4 (excluding) |
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/31df8bc4d3feca9f9c6b2cd06fd64a111ae1a0e6
- https://git.kernel.org/stable/c/89b1ed358e01e1b0417f5d3b0082359a23355552
- https://git.kernel.org/stable/c/9f38f03ae8d5f57371b71aa6b4275765b65454fd
- https://git.kernel.org/stable/c/c3ae6a3f3ca4f02f6ccddf213c027302586580d0
- https://git.kernel.org/stable/c/31df8bc4d3feca9f9c6b2cd06fd64a111ae1a0e6
- https://git.kernel.org/stable/c/89b1ed358e01e1b0417f5d3b0082359a23355552
- https://git.kernel.org/stable/c/9f38f03ae8d5f57371b71aa6b4275765b65454fd
- https://git.kernel.org/stable/c/c3ae6a3f3ca4f02f6ccddf213c027302586580d0



