A serious security vulnerability, tracked as CVE-2021-46952, was discovered in the Linux kernel network file system (NFS) code. This bug could allow a local attacker to crash the system or possibly escalate privileges by exploiting the mount options passed when mounting an NFS share using UDP. This post will break down the vulnerability with simple explanations, code snippets, exploit scenarios, and patch details so you can understand the risk and how it was fixed.
What is the Vulnerability?
In the Linux kernel's NFS code, the function xprt_calc_majortimeo() calculates a major timeout for NFS UDP communications using the retrans parameter (passed as a mount option). The code used the retrans value as a bit shift count:
timeout = 1 << retrans;
If a user passes an unusually large value for retrans (such as 64 or higher), this shifts the bit by 64 or more places in a 64-bit integer, which is undefined behavior in C—it can crash the kernel or lead to unpredictable results.
In short: Passing a crazy high number to retrans breaks the kernel!
Here's the critical part of the code, simplified for clarity
unsigned long xprt_calc_majortimeo(unsigned int retrans)
{
return 1UL << retrans; // Dangerous if retrans >= 64!
}
There was no check for how big retrans could be. If an attacker (or an automated tool like syzkaller) tries to mount an NFS share with something like retrans=100, the shift goes out of bounds.
An attacker could exploit this by running a command as a local user
mount -t nfs -o retrans=100,proto=udp <server>:/export /mnt
Because of the unchecked shift in the kernel, this can lead to a crash (kernel panic) or undefined behavior. While this is mostly a Denial-of-Service (DoS), sometimes undefined behavior can be a stepping stone for kernel exploits or privilege escalation, though no full exploit for escalation was published.
The Fix
The Linux kernel maintainers patched this code to verify the value of retrans before using it as a shift value. If retrans >= 64 (for a 64-bit integer), the kernel now rejects the mount with an error.
Here's a snippet illustrating the new logic
if (retrans >= sizeof(unsigned long) * 8) {
pr_err("NFS: retrans option too large (%u)\n", retrans);
return -EINVAL; // Fails mount: invalid argument
}
timeout = 1UL << retrans;
Patch Reference:
Linux kernel commit fixing CVE-2021-46952
Original References
- CVE Detail Page for CVE-2021-46952
- Linux Kernel Patch Discussion
- NFS Maintainers' Git Commit
Impact
- Who is affected: Anyone running a Linux kernel with NFS support, especially if NFS shares are mounted with proto=udp.
- Attack vector: Local user or potentially remote, if custom mount options can be fed to the kernel.
Conclusion
CVE-2021-46952 is a typical example of how a small coding oversight—a missing value check—can open a huge security hole. Even kernel parameters that seem harmless, like a timeout count, can become dangerous if not validated. Make sure your systems are up to date and configurations are locked down. This also highlights the importance of ongoing fuzz testing (like what syzkaller does) for foundational code like the Linux kernel.
Stay patched, stay safe!
_Exclusive writeup by ChatGPT (2024). All links, code, and explanations researched and summarized from primary sources._
Timeline
Published on: 02/27/2024 19:04:06 UTC
Last modified on: 04/10/2024 20:15:42 UTC