The Linux Kernel is well known for its reliability, performance, and flexibility. However, like any other software, it is not immune to vulnerabilities. In this long read post, we will delve into a recently resolved vulnerability in the Linux kernel: "ocfs2: free inode when ocfs2_get_init_inode() fails". We will discuss its details, share code snippets, provide links to original references, and learn about the solution implemented to fix this issue.

The Vulnerability - CVE-2024-56630

In the Linux kernel, there was a vulnerability where the ocfs2_get_init_inode() function would fail. Ocfs2 is the Oracle Cluster File System, version 2, commonly found in Linux operating systems. In a nutshell, when the ocfs2_get_init_inode() function fails, it has a direct impact on the system's performance and stability, sometimes leading to data corruption or data loss.

The bot "syzbot" identified the problem, reporting busy inodes even after unmounting the filesystem. This issue was noticed after commit 9c89feaf826 ("ocfs2: Handle error from dquot_initialize()"). That particular commit did not account for one scenario when new_inode() succeeded and dquot_initialize() failed, which caused the system to leak inodes and exhaust inode cache.

Here's a code snippet showcasing the issue

static int ocfs2_get_init_inode(struct inode *inode, int flags) {
  int status;
  struct hipd_private_inode *ip = OCFS2_I(inode);
  struct ocfs2_inode_info *oi = &ip->ip_dyn_features;

  inode_init_once(inode); /* initialize inode */

  /* ... more inode initialization ... */

  status = dquot_initialize(inode);  /* initialize disk quota */
  if (status)
    return status;

  /* ... more initialization ... */

  return ;
}

Notice that on failure in dquot_initialize(), iput() is not called for the successful new_inode() call, leaving an allocated but uninitialized inode.

The Solution

To fix the vulnerability, the developers added a call to iput() when dquot_initialize() fails after new_inode() succeeded. Here's a code snippet showcasing the solution:

static int ocfs2_get_init_inode(struct inode *inode, int flags) {
  int status;
  struct hipd_private_inode *ip = OCFS2_I(inode);
  struct ocfs2_inode_info *oi = &ip->ip_dyn_features;

  inode_init_once(inode); /* initialize inode */

  /* ... more inode initialization ... */

  status = dquot_initialize(inode);  /* initialize disk quota */
  if (status) {
    iput(inode); /* call iput() to properly free the allocated inode */
    return status;
  }

  /* ... more initialization ... */

  return ;
}

By adding iput() when dquot_initialize() fails, the resolved vulnerability ensures the inode is properly freed and prevents inode leaks and performance issues associated with this bug.

Original References

Here are some links to original references for more in-depth information about the vulnerability, its discovery, and the solution:

1. Linux kernel source code commit 9c89feaf826
2. syzbot report on this bug

Conclusion

In conclusion, even the most reliable software can have vulnerabilities. Thanks to the diligent work of developers and systems like syzbot, the "ocfs2: free inode when ocfs2_get_init_inode() fails" vulnerability (CVE-2024-56630) was identified and resolved. By recognizing these issues and implementing solutions in a timely manner, the Linux Kernel maintains its reputation for reliability, performance, and security.

Timeline

Published on: 12/27/2024 15:15:22 UTC
Last modified on: 01/20/2025 06:24:29 UTC