A high-severity cache invalidation bug in the Linux kernel has been uncovered, which could allow an attacker to gain root privileges on the targeted system.
This is the second kernel flaw in Linux to debut in the last week; a local-privilege escalation issue was also recently discovered.
The flaw (CVE-2018-17182), which exists in Linux memory management in kernel versions 3.16 through 4.18.8, can be exploited in many different ways, “even from relatively strongly sandboxed contexts,” according to Jann Horn, a researcher with Google Project Zero.
The Linux team fixed the problem in the upstream kernel tree within two days of Horn responsibly reporting it on Sept. 18, which Horn said was “exceptionally fast, compared to the fix times of other software vendors.”
The bad news is that Debian stable and Ubuntu releases 16.04 and 18.04 have not yet patched the vulnerability – and Android users remain at risk.
“Android only ships security updates once a month,” Horn said, in a blog post on the flaw this week. “Therefore, when a security-critical fix is available in an upstream stable kernel, it can still take weeks before the fix is actually available to users—especially if the security impact is not announced publicly.”
Horn explained that the bug stems from an overflow problem.
When the Linux kernel looks up the virtual memory area (VMA) to handle a page fault, there’s a slow path that involves crawling through all of the VMAs in the code in order to find the right resolution to the problem. Because this is inefficient and comes with a performance hit, coders built in a fast-track alternative that can be used if the VMA was recently used.
This caching approach however came with its own issues.
“When a VMA is freed, the VMA caches of all threads must be invalidated – otherwise, the next VMA lookup would follow a dangling pointer. However, since a process can have many threads, simply iterating through the VMA caches of all threads would be a performance problem,” Horn explained.
The fix for this involves tagging threads with sequence numbers to distinguish the various fast-track paths from each other. But the sequence numbers are only 32 bits wide, meaning that it’s possible for them to overflow. As an optimization in version 3.16, overflow handling logic was added to the mix, which introduced a flaw leading to a use-after-free (UAF) vulnerability, a.k.a. CVE-2018-17182.
UAF specifically refers to the attempt to access memory after it has been freed; incorrect UAF coding (say, allowing a program to continue to use a pointer after it has been freed) can cause a program to crash. UAF vulnerabilities meanwhile are a class of memory corruption bug stemming from confusion over which part of the program is responsible for freeing the memory. In the case of this vulnerability, this opens the door to exploits that allow root access and the execution of arbitrary code.
Users can make CVE-2018-17182 a non-issue by updating to an upstream stable release, either 4.18.9, 4.14.71, 4.9.128, 4.4.157 or 3.16.58.
“The bug was fixed by changing the [VMA] sequence numbers to 64 bits, thereby making an overflow infeasible and removing the overflow handling logic,” Horn said.
For unpatched systems, there are a myriad of ways to use the vulnerability to attack a target, Horn pointed out. However, the configuration of the kernel can have a big impact – and in this case, successful exploitation becomes a more trivial thing to do in environments that use Linux kernels that haven’t been configured for increased security, according to Horn.
For instance, an attacker attempting to exploit a kernel bug might benefit from the ability to retry an attack multiple times without triggering system reboots.
“An attacker with the ability to read the crash log produced by the first attempt might even be able to use that information for a more sophisticated second attempt,” the researcher said.
Horn built a proof of concept (PoC) for specifically attacking Ubuntu 18.04 (with kernel linux-image-4.15.0-34-generic at version 4.15.0-34.37) demonstrating this – it allows someone with sufficiently lengthy access – about an hour – to gain root privileges on the targeted system.
“Fundamentally, this bug can be triggered by any process that can run for a sufficiently long time to overflow the reference counter (about an hour if MAP_FIXED is usable) and has the ability to use mmap()/munmap() (to manage memory mappings) and clone() (to create a thread),” he explained.
It seems like a no-brainer to increase security, but the researcher noted that it boils down to making tradeoffs between availability, reliability and security.
“A system owner might want a system to keep running as long as possible, even if parts of the system are crashing, if a sudden kernel panic would cause data loss or downtime of an important service,” he explained.