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&amp;#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 &gt; memory.move_charge_at_immigrate<br /> <br /> for i in range{1..500}<br /> do<br /> mkdir kmem_test<br /> echo $$ &gt; kmem_test/cgroup.procs<br /> sleep 3600 &amp;<br /> echo $$ &gt; cgroup.procs<br /> echo `cat kmem_test/cgroup.procs` &gt; 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-&gt;cached != memcg)<br /> // css_get can change the ref counter from 0 back to 1.<br /> css_get(&amp;memcg-&gt;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().

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)