]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
xfs: check for obviously bad level values in the bmbt root
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 2 Feb 2017 23:13:59 +0000 (15:13 -0800)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 21 Apr 2017 08:11:13 +0000 (10:11 +0200)
BugLink: http://bugs.launchpad.net/bugs/1681875
commit b3bf607d58520ea8c0666aeb4be60dbb724cd3a2 upstream.

We can't handle a bmbt that's taller than BTREE_MAXLEVELS, and there's
no such thing as a zero-level bmbt (for that we have extents format),
so if we see this, send back an error code.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
fs/xfs/libxfs/xfs_inode_fork.c

index 421341f93bea9ab1e965e9cb54316041f1a8b74c..25c1e078aef6a5925c12f2cc91b0d18b8b38711b 100644 (file)
@@ -26,6 +26,7 @@
 #include "xfs_inode.h"
 #include "xfs_trans.h"
 #include "xfs_inode_item.h"
+#include "xfs_btree.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_bmap.h"
 #include "xfs_error.h"
@@ -429,11 +430,13 @@ xfs_iformat_btree(
        /* REFERENCED */
        int                     nrecs;
        int                     size;
+       int                     level;
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
        dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
        size = XFS_BMAP_BROOT_SPACE(mp, dfp);
        nrecs = be16_to_cpu(dfp->bb_numrecs);
+       level = be16_to_cpu(dfp->bb_level);
 
        /*
         * blow out if -- fork has less extents than can fit in
@@ -446,7 +449,8 @@ xfs_iformat_btree(
                                        XFS_IFORK_MAXEXT(ip, whichfork) ||
                     XFS_BMDR_SPACE_CALC(nrecs) >
                                        XFS_DFORK_SIZE(dip, mp, whichfork) ||
-                    XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
+                    XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
+                    level == 0 || level > XFS_BTREE_MAXLEVELS) {
                xfs_warn(mp, "corrupt inode %Lu (btree).",
                                        (unsigned long long) ip->i_ino);
                XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW,