From: Greg Kroah-Hartman Date: Tue, 7 Aug 2018 14:30:01 +0000 (+0200) Subject: 4.17-stable patches X-Git-Tag: v4.17.14~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f20e861697e6e5c63606fc4a7a4f13021db82f1b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.17-stable patches added patches: xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch xfs-validate-cached-inodes-are-free-when-allocated.patch --- diff --git a/queue-4.17/series b/queue-4.17/series index 3b525c772b1..3dd9ee0957a 100644 --- a/queue-4.17/series +++ b/queue-4.17/series @@ -14,3 +14,5 @@ ring_buffer-tracing-inherit-the-tracing-setting-to-next-ring-buffer.patch i2c-imx-fix-reinit_completion-use.patch btrfs-fix-file-data-corruption-after-cloning-a-range-and-fsync.patch partially-revert-block-fail-op_is_write-requests-to-read-only-partitions.patch +xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch +xfs-validate-cached-inodes-are-free-when-allocated.patch diff --git a/queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch b/queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch new file mode 100644 index 00000000000..be8c53a998f --- /dev/null +++ b/queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch @@ -0,0 +1,45 @@ +From bb3d48dcf86a97dc25fe9fc2c11938e19cb4399a Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Fri, 8 Jun 2018 09:53:49 -0700 +Subject: xfs: don't call xfs_da_shrink_inode with NULL bp + +From: Eric Sandeen + +commit bb3d48dcf86a97dc25fe9fc2c11938e19cb4399a upstream. + +xfs_attr3_leaf_create may have errored out before instantiating a buffer, +for example if the blkno is out of range. In that case there is no work +to do to remove it, and in fact xfs_da_shrink_inode will lead to an oops +if we try. + +This also seems to fix a flaw where the original error from +xfs_attr3_leaf_create gets overwritten in the cleanup case, and it +removes a pointless assignment to bp which isn't used after this. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199969 +Reported-by: Xu, Wen +Tested-by: Xu, Wen +Signed-off-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Cc: Eduardo Valentin +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/libxfs/xfs_attr_leaf.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/xfs/libxfs/xfs_attr_leaf.c ++++ b/fs/xfs/libxfs/xfs_attr_leaf.c +@@ -803,9 +803,8 @@ xfs_attr_shortform_to_leaf( + ASSERT(blkno == 0); + error = xfs_attr3_leaf_create(args, blkno, &bp); + if (error) { +- error = xfs_da_shrink_inode(args, 0, bp); +- bp = NULL; +- if (error) ++ /* xfs_attr3_leaf_create may not have instantiated a block */ ++ if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0)) + goto out; + xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ + memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ diff --git a/queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch b/queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch new file mode 100644 index 00000000000..302a97bc8ab --- /dev/null +++ b/queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch @@ -0,0 +1,157 @@ +From afca6c5b2595fc44383919fba740c194b0b76aff Mon Sep 17 00:00:00 2001 +From: Dave Chinner +Date: Tue, 17 Apr 2018 17:17:34 -0700 +Subject: xfs: validate cached inodes are free when allocated + +From: Dave Chinner + +commit afca6c5b2595fc44383919fba740c194b0b76aff upstream. + +A recent fuzzed filesystem image cached random dcache corruption +when the reproducer was run. This often showed up as panics in +lookup_slow() on a null inode->i_ops pointer when doing pathwalks. + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 +.... +Call Trace: + lookup_slow+0x44/0x60 + walk_component+0x3dd/0x9f0 + link_path_walk+0x4a7/0x830 + path_lookupat+0xc1/0x470 + filename_lookup+0x129/0x270 + user_path_at_empty+0x36/0x40 + path_listxattr+0x98/0x110 + SyS_listxattr+0x13/0x20 + do_syscall_64+0xf5/0x280 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 + +but had many different failure modes including deadlocks trying to +lock the inode that was just allocated or KASAN reports of +use-after-free violations. + +The cause of the problem was a corrupt INOBT on a v4 fs where the +root inode was marked as free in the inobt record. Hence when we +allocated an inode, it chose the root inode to allocate, found it in +the cache and re-initialised it. + +We recently fixed a similar inode allocation issue caused by inobt +record corruption problem in xfs_iget_cache_miss() in commit +ee457001ed6c ("xfs: catch inode allocation state mismatch +corruption"). This change adds similar checks to the cache-hit path +to catch it, and turns the reproducer into a corruption shutdown +situation. + +Reported-by: Wen Xu +Signed-Off-By: Dave Chinner +Reviewed-by: Christoph Hellwig +Reviewed-by: Carlos Maiolino +Reviewed-by: Darrick J. Wong +[darrick: fix typos in comment] +Signed-off-by: Darrick J. Wong +Cc: Eduardo Valentin +Signed-off-by: Greg Kroah-Hartman + +--- + fs/xfs/xfs_icache.c | 73 ++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 48 insertions(+), 25 deletions(-) + +--- a/fs/xfs/xfs_icache.c ++++ b/fs/xfs/xfs_icache.c +@@ -309,6 +309,46 @@ xfs_reinit_inode( + } + + /* ++ * If we are allocating a new inode, then check what was returned is ++ * actually a free, empty inode. If we are not allocating an inode, ++ * then check we didn't find a free inode. ++ * ++ * Returns: ++ * 0 if the inode free state matches the lookup context ++ * -ENOENT if the inode is free and we are not allocating ++ * -EFSCORRUPTED if there is any state mismatch at all ++ */ ++static int ++xfs_iget_check_free_state( ++ struct xfs_inode *ip, ++ int flags) ++{ ++ if (flags & XFS_IGET_CREATE) { ++ /* should be a free inode */ ++ if (VFS_I(ip)->i_mode != 0) { ++ xfs_warn(ip->i_mount, ++"Corruption detected! Free inode 0x%llx not marked free! (mode 0x%x)", ++ ip->i_ino, VFS_I(ip)->i_mode); ++ return -EFSCORRUPTED; ++ } ++ ++ if (ip->i_d.di_nblocks != 0) { ++ xfs_warn(ip->i_mount, ++"Corruption detected! Free inode 0x%llx has blocks allocated!", ++ ip->i_ino); ++ return -EFSCORRUPTED; ++ } ++ return 0; ++ } ++ ++ /* should be an allocated inode */ ++ if (VFS_I(ip)->i_mode == 0) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++/* + * Check the validity of the inode we just found it the cache + */ + static int +@@ -357,12 +397,12 @@ xfs_iget_cache_hit( + } + + /* +- * If lookup is racing with unlink return an error immediately. ++ * Check the inode free state is valid. This also detects lookup ++ * racing with unlinks. + */ +- if (VFS_I(ip)->i_mode == 0 && !(flags & XFS_IGET_CREATE)) { +- error = -ENOENT; ++ error = xfs_iget_check_free_state(ip, flags); ++ if (error) + goto out_error; +- } + + /* + * If IRECLAIMABLE is set, we've torn down the VFS inode already. +@@ -485,29 +525,12 @@ xfs_iget_cache_miss( + + + /* +- * If we are allocating a new inode, then check what was returned is +- * actually a free, empty inode. If we are not allocating an inode, +- * the check we didn't find a free inode. ++ * Check the inode free state is valid. This also detects lookup ++ * racing with unlinks. + */ +- if (flags & XFS_IGET_CREATE) { +- if (VFS_I(ip)->i_mode != 0) { +- xfs_warn(mp, +-"Corruption detected! Free inode 0x%llx not marked free on disk", +- ino); +- error = -EFSCORRUPTED; +- goto out_destroy; +- } +- if (ip->i_d.di_nblocks != 0) { +- xfs_warn(mp, +-"Corruption detected! Free inode 0x%llx has blocks allocated!", +- ino); +- error = -EFSCORRUPTED; +- goto out_destroy; +- } +- } else if (VFS_I(ip)->i_mode == 0) { +- error = -ENOENT; ++ error = xfs_iget_check_free_state(ip, flags); ++ if (error) + goto out_destroy; +- } + + /* + * Preload the radix tree so we can insert safely under the