summaryrefslogtreecommitdiff
path: root/fs/ext4/inline.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2018-08-27 09:22:45 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-29 03:08:53 -0700
commit7619c7f66012b18aa634b1091e11ca12e574bbdb (patch)
tree3a81e5e6500d7b62f785cf0cce876daace1c1ba1 /fs/ext4/inline.c
parent1aa698b65186c13ed775896ed1dfec7c26c73d60 (diff)
ext4: avoid divide by zero fault when deleting corrupted inline directories
commit 4d982e25d0bdc83d8c64e66fdeca0b89240b3b85 upstream. 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 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/ext4/inline.c')
-rw-r--r--fs/ext4/inline.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index c449bc089c94..1e7a9774119c 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1756,6 +1756,7 @@ int empty_inline_dir(struct inode *dir, int *has_inline_data)
{
int err, inline_size;
struct ext4_iloc iloc;
+ size_t inline_len;
void *inline_pos;
unsigned int offset;
struct ext4_dir_entry_2 *de;
@@ -1783,8 +1784,9 @@ int empty_inline_dir(struct inode *dir, int *has_inline_data)
goto out;
}
+ inline_len = ext4_get_inline_size(dir);
offset = EXT4_INLINE_DOTDOT_SIZE;
- while (offset < dir->i_size) {
+ while (offset < inline_len) {
de = ext4_get_inline_entry(dir, &iloc, offset,
&inline_pos, &inline_size);
if (ext4_check_dir_entry(dir, NULL, de,