Security in the Android operating system heavily depends on the safety of the Linux kernel. What happens when the kernel has a bug that attackers can exploit with no user interaction? Let’s break down CVE-2022-20141—a critical use-after-free vulnerability in the IGMP (Internet Group Management Protocol) implementation in the Android kernel.
Discovered by Google (Android ID: A-112551163), this bug could let local attackers escalate their privileges without needing additional execution rights or user action.
The Culprit: ip_check_mc_rcu()
The problematic function is ip_check_mc_rcu in igmp.c—this function is responsible for checking if a given network address is part of a multicast group. It’s part of the Linux kernel’s network stack.
What is Use-After-Free?
A use-after-free occurs when a program continues to use memory (like a struct or object) after it’s been freed and potentially reallocated by something else. In kernel space, this can yield powerful attack vectors, letting a user-run process read or write to privileged memory.
What Really Happened Here?
The short version: Improper locking around the network socket data structures in IGMP handling can allow a race condition—two threads can mess with the same memory at the same time. If one thread frees a structure while another is reading from it, you hit a _use-after-free_.
From Google’s upstream patch, the bug occurs when opening and closing INET sockets under specific timing—no root or su needed!
Here’s a simplified view of the old code in igmp.c for ip_check_mc_rcu
int ip_check_mc_rcu(struct net_device *dev, __be32 mc_addr, __be32 src_addr)
{
struct ip_mc_list *im;
for (im = rcu_dereference(dev->ip_mc_list);
im;
im = rcu_dereference(im->next_rcu)) {
if (im->multiaddr == mc_addr) {
if (!src_addr || im->src_addr == src_addr)
return 1;
}
}
return ;
}
The dev->ip_mc_list is an RCU-protected list.
- If another thread or CPU frees im during our iteration (say, because a socket was closed), then the pointer becomes invalid—but we still try to use its members.
Upstream Fix
The upstream kernel fixed this by ensuring proper locking and RCU synchronization. For example, using rcu_read_lock() and rcu_read_unlock() (and other means) to guarantee a safe memory access window.
Reference:
- Upstream Kernel Commit
Who can exploit this?
Any local user with the ability to open/close sockets (almost every app or user process on Android) could potentially trigger this. No root needed!
User Interaction
None. It’s enough for an attacker to hammer the kernel with socket open/close requests—perfect for privilege escalation in malware or rooting attempts.
Create multiple INET sockets that join & leave multicast groups rapidly.
2. Exploit the Race Condition by creating threads: one thread closes sockets (freeing the ip_mc_list structure), while another calls ip_check_mc_rcu() (using the now-freed memory).
3. Memory Corruption: By controlling freed memory, a malicious program might inject crafted data (or pointers), leading to privilege escalation, information leaks, or potential kernel code execution.
Illustrative Exploit Skeleton (Pseudo-C)
// Pseudo-code outline. Real exploitation is much more complex.
void *hammer_open_close(void *arg) {
while (true) {
int sock = socket(AF_INET, SOCK_DGRAM, );
// Join multicast
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, ...);
// Leave group, close socket, triggers structure removal
close(sock);
}
}
// In parallel, call some multicast functions rapidly:
void *trigger_race(void *arg) {
while (true) {
// This calls ip_check_mc_rcu internally!
some_mc_api_call(...);
}
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, hammer_open_close, NULL);
pthread_create(&t2, NULL, trigger_race, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
}
Warning:
*This code is for educational illustration only. Real-world exploitation is much harder due to kernel protections.*
Information leaks from kernel space
Android Versions Affected:
Any device running vulnerable kernel builds
- Applies wherever igmp.c and this logic is present (Android and possibly some upstream Linux variants)
Android Security ID: A-112551163
Apply Security Updates:
Google patched this vulnerability months ago. Update to the latest Android kernel version as offered by your OEM.
Verify Vendor Patch:
If you custom-build Android kernels, make sure you pull the upstream fix or backport this commit.
Android Security Bulletin (June 2022):
https://source.android.com/docs/security/bulletin/2022-06-01
Upstream Kernel Commit:
CVE Entries:
Conclusion
CVE-2022-20141 is a clear example of how even low-level network code can present serious risks to end-users. Bugs like use-after-free vulnerabilities in critical components can open the door to privilege escalation and device takeover, even if the attacker doesn’t have root to start.
Key Takeaway:
Always update your devices. Even small security patches can prevent catastrophic attacks. If you build or maintain Android forks, do your homework on upstream kernel bugs.
Timeline
Published on: 06/15/2022 14:15:00 UTC
Last modified on: 06/23/2022 20:21:00 UTC