kvm-x86-inject-ud-on-emulated-xsetbv-if-xsaves-isn-t-enabled.patch
arm64-topology-fix-possible-overflow-in-amu_fie_setup.patch
vmlinux.lds.h-cfi-reduce-alignment-of-jump-table-to-function-alignment.patch
+xfs-reorder-iunlink-remove-operation-in-xfs_ifree.patch
+xfs-fix-xfs_ifree-error-handling-to-not-leak-perag-ref.patch
+xfs-validate-inode-fork-size-against-fork-format.patch
--- /dev/null
+From foo@baz Sat Sep 24 11:39:38 AM CEST 2022
+From: Leah Rumancik <leah.rumancik@gmail.com>
+Date: Thu, 22 Sep 2022 08:15:00 -0700
+Subject: xfs: fix xfs_ifree() error handling to not leak perag ref
+To: stable@vger.kernel.org
+Cc: linux-xfs@vger.kernel.org, amir73il@gmail.com, chandan.babu@oracle.com, Brian Foster <bfoster@redhat.com>, "Darrick J . Wong" <djwong@kernel.org>, Dave Chinner <dchinner@redhat.com>, Dave Chinner <david@fromorbit.com>, Leah Rumancik <leah.rumancik@gmail.com>
+Message-ID: <20220922151501.2297190-3-leah.rumancik@gmail.com>
+
+From: Brian Foster <bfoster@redhat.com>
+
+[ Upstream commit 6f5097e3367a7c0751e165e4c15bc30511a4ba38 ]
+
+For some reason commit 9a5280b312e2e ("xfs: reorder iunlink remove
+operation in xfs_ifree") replaced a jump to the exit path in the
+event of an xfs_difree() error with a direct return, which skips
+releasing the perag reference acquired at the top of the function.
+Restore the original code to drop the reference on error.
+
+Fixes: 9a5280b312e2e ("xfs: reorder iunlink remove operation in xfs_ifree")
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -2634,7 +2634,7 @@ xfs_ifree(
+ */
+ error = xfs_difree(tp, pag, ip->i_ino, &xic);
+ if (error)
+- return error;
++ goto out;
+
+ error = xfs_iunlink_remove(tp, pag, ip);
+ if (error)
--- /dev/null
+From foo@baz Sat Sep 24 11:39:38 AM CEST 2022
+From: Leah Rumancik <leah.rumancik@gmail.com>
+Date: Thu, 22 Sep 2022 08:14:59 -0700
+Subject: xfs: reorder iunlink remove operation in xfs_ifree
+To: stable@vger.kernel.org
+Cc: linux-xfs@vger.kernel.org, amir73il@gmail.com, chandan.babu@oracle.com, Dave Chinner <dchinner@redhat.com>, Frank Hofmann <fhofmann@cloudflare.com>, "Darrick J . Wong" <darrick.wong@oracle.com>, Dave Chinner <david@fromorbit.com>, Leah Rumancik <leah.rumancik@gmail.com>, "Darrick J . Wong" <djwong@kernel.org>
+Message-ID: <20220922151501.2297190-2-leah.rumancik@gmail.com>
+
+From: Dave Chinner <dchinner@redhat.com>
+
+[ Upstream commit 9a5280b312e2e7898b6397b2ca3cfd03f67d7be1 ]
+
+The O_TMPFILE creation implementation creates a specific order of
+operations for inode allocation/freeing and unlinked list
+modification. Currently both are serialised by the AGI, so the order
+doesn't strictly matter as long as the are both in the same
+transaction.
+
+However, if we want to move the unlinked list insertions largely out
+from under the AGI lock, then we have to be concerned about the
+order in which we do unlinked list modification operations.
+O_TMPFILE creation tells us this order is inode allocation/free,
+then unlinked list modification.
+
+Change xfs_ifree() to use this same ordering on unlinked list
+removal. This way we always guarantee that when we enter the
+iunlinked list removal code from this path, we already have the AGI
+locked and we don't have to worry about lock nesting AGI reads
+inside unlink list locks because it's already locked and attached to
+the transaction.
+
+We can do this safely as the inode freeing and unlinked list removal
+are done in the same transaction and hence are atomic operations
+with respect to log recovery.
+
+Reported-by: Frank Hofmann <fhofmann@cloudflare.com>
+Fixes: 298f7bec503f ("xfs: pin inode backing buffer to the inode log item")
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_inode.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -2599,14 +2599,13 @@ xfs_ifree_cluster(
+ }
+
+ /*
+- * This is called to return an inode to the inode free list.
+- * The inode should already be truncated to 0 length and have
+- * no pages associated with it. This routine also assumes that
+- * the inode is already a part of the transaction.
++ * This is called to return an inode to the inode free list. The inode should
++ * already be truncated to 0 length and have no pages associated with it. This
++ * routine also assumes that the inode is already a part of the transaction.
+ *
+- * The on-disk copy of the inode will have been added to the list
+- * of unlinked inodes in the AGI. We need to remove the inode from
+- * that list atomically with respect to freeing it here.
++ * The on-disk copy of the inode will have been added to the list of unlinked
++ * inodes in the AGI. We need to remove the inode from that list atomically with
++ * respect to freeing it here.
+ */
+ int
+ xfs_ifree(
+@@ -2628,13 +2627,16 @@ xfs_ifree(
+ pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+
+ /*
+- * Pull the on-disk inode from the AGI unlinked list.
++ * Free the inode first so that we guarantee that the AGI lock is going
++ * to be taken before we remove the inode from the unlinked list. This
++ * makes the AGI lock -> unlinked list modification order the same as
++ * used in O_TMPFILE creation.
+ */
+- error = xfs_iunlink_remove(tp, pag, ip);
++ error = xfs_difree(tp, pag, ip->i_ino, &xic);
+ if (error)
+- goto out;
++ return error;
+
+- error = xfs_difree(tp, pag, ip->i_ino, &xic);
++ error = xfs_iunlink_remove(tp, pag, ip);
+ if (error)
+ goto out;
+
--- /dev/null
+From foo@baz Sat Sep 24 11:39:38 AM CEST 2022
+From: Leah Rumancik <leah.rumancik@gmail.com>
+Date: Thu, 22 Sep 2022 08:15:01 -0700
+Subject: xfs: validate inode fork size against fork format
+To: stable@vger.kernel.org
+Cc: linux-xfs@vger.kernel.org, amir73il@gmail.com, chandan.babu@oracle.com, Dave Chinner <dchinner@redhat.com>, Christoph Hellwig <hch@lst.de>, "Darrick J . Wong" <djwong@kernel.org>, Dave Chinner <david@fromorbit.com>, Leah Rumancik <leah.rumancik@gmail.com>
+Message-ID: <20220922151501.2297190-4-leah.rumancik@gmail.com>
+
+From: Dave Chinner <dchinner@redhat.com>
+
+[ Upstream commit 1eb70f54c445fcbb25817841e774adb3d912f3e8 ]
+
+xfs_repair catches fork size/format mismatches, but the in-kernel
+verifier doesn't, leading to null pointer failures when attempting
+to perform operations on the fork. This can occur in the
+xfs_dir_is_empty() where the in-memory fork format does not match
+the size and so the fork data pointer is accessed incorrectly.
+
+Note: this causes new failures in xfs/348 which is testing mode vs
+ftype mismatches. We now detect a regular file that has been changed
+to a directory or symlink mode as being corrupt because the data
+fork is for a symlink or directory should be in local form when
+there are only 3 bytes of data in the data fork. Hence the inode
+verify for the regular file now fires w/ -EFSCORRUPTED because
+the inode fork format does not match the format the corrupted mode
+says it should be in.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_inode_buf.c | 35 ++++++++++++++++++++++++++---------
+ 1 file changed, 26 insertions(+), 9 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_inode_buf.c
++++ b/fs/xfs/libxfs/xfs_inode_buf.c
+@@ -337,19 +337,36 @@ xfs_dinode_verify_fork(
+ int whichfork)
+ {
+ uint32_t di_nextents = XFS_DFORK_NEXTENTS(dip, whichfork);
++ mode_t mode = be16_to_cpu(dip->di_mode);
++ uint32_t fork_size = XFS_DFORK_SIZE(dip, mp, whichfork);
++ uint32_t fork_format = XFS_DFORK_FORMAT(dip, whichfork);
+
+- switch (XFS_DFORK_FORMAT(dip, whichfork)) {
++ /*
++ * For fork types that can contain local data, check that the fork
++ * format matches the size of local data contained within the fork.
++ *
++ * For all types, check that when the size says the should be in extent
++ * or btree format, the inode isn't claiming it is in local format.
++ */
++ if (whichfork == XFS_DATA_FORK) {
++ if (S_ISDIR(mode) || S_ISLNK(mode)) {
++ if (be64_to_cpu(dip->di_size) <= fork_size &&
++ fork_format != XFS_DINODE_FMT_LOCAL)
++ return __this_address;
++ }
++
++ if (be64_to_cpu(dip->di_size) > fork_size &&
++ fork_format == XFS_DINODE_FMT_LOCAL)
++ return __this_address;
++ }
++
++ switch (fork_format) {
+ case XFS_DINODE_FMT_LOCAL:
+ /*
+- * no local regular files yet
++ * No local regular files yet.
+ */
+- if (whichfork == XFS_DATA_FORK) {
+- if (S_ISREG(be16_to_cpu(dip->di_mode)))
+- return __this_address;
+- if (be64_to_cpu(dip->di_size) >
+- XFS_DFORK_SIZE(dip, mp, whichfork))
+- return __this_address;
+- }
++ if (S_ISREG(mode) && whichfork == XFS_DATA_FORK)
++ return __this_address;
+ if (di_nextents)
+ return __this_address;
+ break;