]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ext4: always verify the magic number in xattr blocks
authorTheodore Ts'o <tytso@mit.edu>
Wed, 13 Jun 2018 04:51:28 +0000 (00:51 -0400)
committerBrian Maly <brian.maly@oracle.com>
Tue, 19 Mar 2019 16:24:52 +0000 (12:24 -0400)
commit 513f86d73855ce556ea9522b6bfd79f87356dc3a upstream.

If there an inode points to a block which is also some other type of
metadata block (such as a block allocation bitmap), the
buffer_verified flag can be set when it was validated as that other
metadata block type; however, it would make a really terrible external
attribute block.  The reason why we use the verified flag is to avoid
constantly reverifying the block.  However, it doesn't take much
overhead to make sure the magic number of the xattr block is correct,
and this will avoid potential crashes.

This addresses CVE-2018-10879.

https://bugzilla.kernel.org/show_bug.cgi?id=200001

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 3150e8913b957d71398511a0580606e181153d10)

Orabug: 29437127
CVE: CVE-2018-10879

Signed-off-by: John Donnelly <John.P.Donnelly@oracle.com>
Reviewed-by: Jack Vogel <jack.vogel@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
Conflicts:
fs/ext4/xattr.c

Signed-off-by: Brian Maly <brian.maly@oracle.com>
fs/ext4/xattr.c

index 72721c8c3585d07f3b8b7b7b4de3cf0e491b186f..fc023d3af21eaf5b6d1bf72b185657eba56a203e 100644 (file)
@@ -213,25 +213,37 @@ ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
 }
 
 static inline int
-ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
+__ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
+                               const char *function, unsigned int line)
 {
-       int error;
+       int error = -EFSCORRUPTED;
 
+       if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
+           BHDR(bh)->h_blocks != cpu_to_le32(1))
+               goto errout;
        if (buffer_verified(bh))
                return 0;
+       
+       error = -EFSBADCRC;
 
-       if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
-           BHDR(bh)->h_blocks != cpu_to_le32(1))
-               return -EIO;
        if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
-               return -EIO;
+               goto errout;
+
        error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
                                       bh->b_data);
-       if (!error)
+errout:
+       if (error)
+               __ext4_error_inode(inode, function, line, 0,
+                                  "corrupted xattr block %llu",
+                                  (unsigned long long) bh->b_blocknr);
+       else
                set_buffer_verified(bh);
        return error;
 }
 
+#define ext4_xattr_check_block(inode, bh) \
+        __ext4_xattr_check_block((inode), (bh),  __func__, __LINE__)
+
 static inline int
 ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size)
 {