Bug 200933
Summary: | Divide zero in __ext4_check_dir_entry | ||
---|---|---|---|
Product: | File System | Reporter: | Wen Xu (wen.xu) |
Component: | ext4 | Assignee: | fs_ext4 (fs_ext4) |
Status: | ASSIGNED --- | ||
Severity: | normal | CC: | tytso, wen.xu |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 4.18 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
The (compressed) crafted image which causes crash
poc Simplified crafted image |
Description
Wen Xu
2018-08-25 05:14:33 UTC
Created attachment 278083 [details]
poc
Created attachment 278125 [details]
Simplified crafted image
Here is a simplified crafted image. Here is also a simplified reproducer:
mount poc-200933.img.simplified /mnt
rmdir /mnt/foo/bar
The bug is in the function which checks to see if an inline directory is empty; it is relying on the i_size of the inline directory, and if that value is larger than what is correct, we can either overrun the buffer, or as in this case, trigger a division by zero error when we find that the size of the next "directory entry" is zero. (This didn't trigger a KASAN error because it was still a legal part of the inode table block.)
Patch to fix this: http://patchwork.ozlabs.org/patch/962516/ Note: I will probably be retitling and rewriting the patch description, because on further reflection, it's not possible for this to become a buffer overrun attack. That's because we are checking to make sure the inline directory does not exceed the bounds of the inline data xattr. The size == 0 is coming from the "end of xattr list" marker in the xattr data structure. That has to be there, or we would have declared the xattr data structure to be corrupt before we even tried to parse the inline directory. So the only way the attacker can manifest a problem is by causing the divide by zero in __ext4_check_dir_entry(). So for CVE scoring purposes, this is just a denial of service attack (triggering a kernel divide by zero trap, which doesn't kill the kernel per se, but which leaves various locks and refcounts held, which will eventually cause the system to become wedged). It is not a buffer overrun. Revised description: ext4: avoid divide by zero fault when deleting corrupted inline directories A specially crafted file system can trick empty_inline_dir() into reading past the last valid entry in a inline directory, and then run into the end of xattr marker. This will trigger a divide by zero fault. Fix this by using the size of the inline directory instead of dir->i_size. Also clean up error reporting in __ext4_check_dir_entry so that the message is clearer and more understandable --- and avoids the division by zero trap if the size passed in is zero. (I'm not sure why we coded it that way in the first place; printing offset % size is actually more confusing and less useful.) https://bugzilla.kernel.org/show_bug.cgi?id=200933 Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reported-by: Wen Xu <wen.xu@gatech.edu> Cc: stable@vger.kernel.org |