Bug 199179
Summary: | Invalid pointer dereference when mounting crafted ext4 image in ext4_process_freed_data | ||
---|---|---|---|
Product: | File System | Reporter: | Wen Xu (wen.xu) |
Component: | ext4 | Assignee: | fs_ext4 (fs_ext4) |
Status: | RESOLVED CODE_FIX | ||
Severity: | normal | CC: | jack, tytso, wen.xu |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 4.15.x | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
The crafted image which causes kernel panic
Proposed patch to fix the reported bug. |
Description
Wen Xu
2018-03-22 19:55:32 UTC
Reported by Wen Xu at sslab, gatech. Created attachment 274933 [details]
Proposed patch to fix the reported bug.
Thanks for reporting this bug. The attached should address the problem.
If the root directory has an i_links_count of zero, then when the file
system is mounted, then when ext4_fill_super() notices the problem and
tries to call iput() the root directory in the error return path,
ext4_evict_inode() will try to free the inode on disk, before all of
the file system structures are set up, and this will result in an OOPS
caused by a NULL pointer dereference.
Thank you for the quick response! By the way, I wonder whether I can get CVE numbers assigned for such kinda issues I reported recently?(In reply to Theodore Tso from comment #2) > Created attachment 274933 [details] > Proposed patch to fix the reported bug. > > Thanks for reporting this bug. The attached should address the problem. > > If the root directory has an i_links_count of zero, then when the file > system is mounted, then when ext4_fill_super() notices the problem and > tries to call iput() the root directory in the error return path, > ext4_evict_inode() will try to free the inode on disk, before all of > the file system structures are set up, and this will result in an OOPS > caused by a NULL pointer dereference. Thank you for the quick response! By the way, I wonder whether I can get CVE numbers assigned for such kinda issues I reported recently? Ted, I'm not quite getting it: ext4_iget() should fail getting the root inode in case i_links_count is 0. It should return -ESTALE and mark the inode as bad. So iput() will call ext4_evict_inode() but because the inode is marked as bad, we skip any attempts to delete the inode and just call ext4_clear_inode(). But apparently that didn't happen and ext4_iget() succeeded despite inode having i_links_count == 0. So the question is why the check: if (inode->i_nlink == 0) { if ((inode->i_mode == 0 || !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) && ino != EXT4_BOOT_LOADER_INO) { /* this inode is deleted */ ret = -ESTALE; goto bad_inode; } in ext4_iget() didn't trigger... Well, the root directory i_mode is not 0, and EXT4_ORPHAN_FS is not set. We could add an "ino == EXT4_ROOT_INO ||" to the conditional; that would work too. But if the root inode has i_links_count set to zero, we know for sure it's not a stale NFS handle referncing a deleted inode --- we know the file system must be corrupted, so calling ext4_error() is appropriate. |