From db266749be71c878d1a6377d22c1976828c04f45 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 23 Jul 2022 17:24:53 +0200 Subject: [PATCH] 5.15-stable patches added patches: xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch xfs-fold-perag-loop-iteration-logic-into-helper-function.patch xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch xfs-rename-the-next_agno-perag-iteration-variable.patch xfs-terminate-perag-iteration-reliably-on-agcount.patch --- queue-5.15/series | 6 ++ ...omparisons-in-the-btree-staging-code.patch | 49 ++++++++++ ...e-leak-on-iteration-race-with-growfs.patch | 90 +++++++++++++++++++ ...iteration-logic-into-helper-function.patch | 56 ++++++++++++ ...ent-a-warn_once-in-xfs_ioc_attr_list.patch | 59 ++++++++++++ ...e-next_agno-perag-iteration-variable.patch | 62 +++++++++++++ ...-perag-iteration-reliably-on-agcount.patch | 49 ++++++++++ 7 files changed, 371 insertions(+) create mode 100644 queue-5.15/xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch create mode 100644 queue-5.15/xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch create mode 100644 queue-5.15/xfs-fold-perag-loop-iteration-logic-into-helper-function.patch create mode 100644 queue-5.15/xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch create mode 100644 queue-5.15/xfs-rename-the-next_agno-perag-iteration-variable.patch create mode 100644 queue-5.15/xfs-terminate-perag-iteration-reliably-on-agcount.patch diff --git a/queue-5.15/series b/queue-5.15/series index 1b2923ec677..3cbe2485bf4 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -18,3 +18,9 @@ revert-mt76-mt7921e-fix-possible-probe-failure-after-reboot.patch mt76-mt7921-use-physical-addr-to-unify-register-access.patch mt76-mt7921e-fix-possible-probe-failure-after-reboot.patch mt76-mt7921-fix-the-error-handling-path-of-mt7921_pci_probe.patch +xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch +xfs-fold-perag-loop-iteration-logic-into-helper-function.patch +xfs-rename-the-next_agno-perag-iteration-variable.patch +xfs-terminate-perag-iteration-reliably-on-agcount.patch +xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch +xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch diff --git a/queue-5.15/xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch b/queue-5.15/xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch new file mode 100644 index 00000000000..107010773f7 --- /dev/null +++ b/queue-5.15/xfs-fix-maxlevels-comparisons-in-the-btree-staging-code.patch @@ -0,0 +1,49 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:05 -0700 +Subject: xfs: fix maxlevels comparisons in the btree staging code +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, "Darrick J. Wong" , Chandan Babu R , Christoph Hellwig , Leah Rumancik +Message-ID: <20220721213610.2794134-2-leah.rumancik@gmail.com> + +From: "Darrick J. Wong" + +[ Upstream commit 78e8ec83a404d63dcc86b251f42e4ee8aff27465 ] + +The btree geometry computation function has an off-by-one error in that +it does not allow maximally tall btrees (nlevels == XFS_BTREE_MAXLEVELS). +This can result in repairs failing unnecessarily on very fragmented +filesystems. Subsequent patches to remove MAXLEVELS usage in favor of +the per-btree type computations will make this a much more likely +occurrence. + +Signed-off-by: Darrick J. Wong +Reviewed-by: Chandan Babu R +Reviewed-by: Christoph Hellwig +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_btree_staging.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/xfs/libxfs/xfs_btree_staging.c ++++ b/fs/xfs/libxfs/xfs_btree_staging.c +@@ -662,7 +662,7 @@ xfs_btree_bload_compute_geometry( + xfs_btree_bload_ensure_slack(cur, &bbl->node_slack, 1); + + bbl->nr_records = nr_this_level = nr_records; +- for (cur->bc_nlevels = 1; cur->bc_nlevels < XFS_BTREE_MAXLEVELS;) { ++ for (cur->bc_nlevels = 1; cur->bc_nlevels <= XFS_BTREE_MAXLEVELS;) { + uint64_t level_blocks; + uint64_t dontcare64; + unsigned int level = cur->bc_nlevels - 1; +@@ -724,7 +724,7 @@ xfs_btree_bload_compute_geometry( + nr_this_level = level_blocks; + } + +- if (cur->bc_nlevels == XFS_BTREE_MAXLEVELS) ++ if (cur->bc_nlevels > XFS_BTREE_MAXLEVELS) + return -EOVERFLOW; + + bbl->btree_height = cur->bc_nlevels; diff --git a/queue-5.15/xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch b/queue-5.15/xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch new file mode 100644 index 00000000000..4b51740cc67 --- /dev/null +++ b/queue-5.15/xfs-fix-perag-reference-leak-on-iteration-race-with-growfs.patch @@ -0,0 +1,90 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:09 -0700 +Subject: xfs: fix perag reference leak on iteration race with growfs +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, Brian Foster , Dave Chinner , "Darrick J . Wong" , Leah Rumancik +Message-ID: <20220721213610.2794134-6-leah.rumancik@gmail.com> + +From: Brian Foster + +[ Upstream commit 892a666fafa19ab04b5e948f6c92f98f1dafb489 ] + +The for_each_perag*() set of macros are hacky in that some (i.e. +those based on sb_agcount) rely on the assumption that perag +iteration terminates naturally with a NULL perag at the specified +end_agno. Others allow for the final AG to have a valid perag and +require the calling function to clean up any potential leftover +xfs_perag reference on termination of the loop. + +Aside from providing a subtly inconsistent interface, the former +variant is racy with growfs because growfs can create discoverable +post-eofs perags before the final superblock update that completes +the grow operation and increases sb_agcount. This leads to the +following assert failure (reproduced by xfs/104) in the perag free +path during unmount: + + XFS: Assertion failed: atomic_read(&pag->pag_ref) == 0, file: fs/xfs/libxfs/xfs_ag.c, line: 195 + +This occurs because one of the many for_each_perag() loops in the +code that is expected to terminate with a NULL pag (and thus has no +post-loop xfs_perag_put() check) raced with a growfs and found a +non-NULL post-EOFS perag, but terminated naturally based on the +end_agno check without releasing the post-EOFS perag. + +Rework the iteration logic to lift the agno check from the main for +loop conditional to the iteration helper function. The for loop now +purely terminates on a NULL pag and xfs_perag_next() avoids taking a +reference to any perag beyond end_agno in the first place. + +Fixes: f250eedcf762 ("xfs: make for_each_perag... a first class citizen") +Signed-off-by: Brian Foster +Reviewed-by: Dave Chinner +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_ag.h | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +--- a/fs/xfs/libxfs/xfs_ag.h ++++ b/fs/xfs/libxfs/xfs_ag.h +@@ -116,30 +116,26 @@ void xfs_perag_put(struct xfs_perag *pag + + /* + * Perag iteration APIs +- * +- * XXX: for_each_perag_range() usage really needs an iterator to clean up when +- * we terminate at end_agno because we may have taken a reference to the perag +- * beyond end_agno. Right now callers have to be careful to catch and clean that +- * up themselves. This is not necessary for the callers of for_each_perag() and +- * for_each_perag_from() because they terminate at sb_agcount where there are +- * no perag structures in tree beyond end_agno. + */ + static inline struct xfs_perag * + xfs_perag_next( + struct xfs_perag *pag, +- xfs_agnumber_t *agno) ++ xfs_agnumber_t *agno, ++ xfs_agnumber_t end_agno) + { + struct xfs_mount *mp = pag->pag_mount; + + *agno = pag->pag_agno + 1; + xfs_perag_put(pag); ++ if (*agno > end_agno) ++ return NULL; + return xfs_perag_get(mp, *agno); + } + + #define for_each_perag_range(mp, agno, end_agno, pag) \ + for ((pag) = xfs_perag_get((mp), (agno)); \ +- (pag) != NULL && (agno) <= (end_agno); \ +- (pag) = xfs_perag_next((pag), &(agno))) ++ (pag) != NULL; \ ++ (pag) = xfs_perag_next((pag), &(agno), (end_agno))) + + #define for_each_perag_from(mp, agno, pag) \ + for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag)) diff --git a/queue-5.15/xfs-fold-perag-loop-iteration-logic-into-helper-function.patch b/queue-5.15/xfs-fold-perag-loop-iteration-logic-into-helper-function.patch new file mode 100644 index 00000000000..2cc53693605 --- /dev/null +++ b/queue-5.15/xfs-fold-perag-loop-iteration-logic-into-helper-function.patch @@ -0,0 +1,56 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:06 -0700 +Subject: xfs: fold perag loop iteration logic into helper function +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, Brian Foster , Dave Chinner , "Darrick J . Wong" , Leah Rumancik +Message-ID: <20220721213610.2794134-3-leah.rumancik@gmail.com> + +From: Brian Foster + +[ Upstream commit bf2307b195135ed9c95eebb38920d8bd41843092 ] + +Fold the loop iteration logic into a helper in preparation for +further fixups. No functional change in this patch. + +[backport: dependency for f1788b5e5ee25bedf00bb4d25f82b93820d61189] + +Signed-off-by: Brian Foster +Reviewed-by: Dave Chinner +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_ag.h | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/fs/xfs/libxfs/xfs_ag.h ++++ b/fs/xfs/libxfs/xfs_ag.h +@@ -124,12 +124,22 @@ void xfs_perag_put(struct xfs_perag *pag + * for_each_perag_from() because they terminate at sb_agcount where there are + * no perag structures in tree beyond end_agno. + */ ++static inline struct xfs_perag * ++xfs_perag_next( ++ struct xfs_perag *pag, ++ xfs_agnumber_t *next_agno) ++{ ++ struct xfs_mount *mp = pag->pag_mount; ++ ++ *next_agno = pag->pag_agno + 1; ++ xfs_perag_put(pag); ++ return xfs_perag_get(mp, *next_agno); ++} ++ + #define for_each_perag_range(mp, next_agno, end_agno, pag) \ + for ((pag) = xfs_perag_get((mp), (next_agno)); \ + (pag) != NULL && (next_agno) <= (end_agno); \ +- (next_agno) = (pag)->pag_agno + 1, \ +- xfs_perag_put(pag), \ +- (pag) = xfs_perag_get((mp), (next_agno))) ++ (pag) = xfs_perag_next((pag), &(next_agno))) + + #define for_each_perag_from(mp, next_agno, pag) \ + for_each_perag_range((mp), (next_agno), (mp)->m_sb.sb_agcount, (pag)) diff --git a/queue-5.15/xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch b/queue-5.15/xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch new file mode 100644 index 00000000000..36c66939995 --- /dev/null +++ b/queue-5.15/xfs-prevent-a-warn_once-in-xfs_ioc_attr_list.patch @@ -0,0 +1,59 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:10 -0700 +Subject: xfs: prevent a WARN_ONCE() in xfs_ioc_attr_list() +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, Dan Carpenter , "Darrick J . Wong" , Leah Rumancik +Message-ID: <20220721213610.2794134-7-leah.rumancik@gmail.com> + +From: Dan Carpenter + +[ Upstream commit 6ed6356b07714e0198be3bc3ecccc8b40a212de4 ] + +The "bufsize" comes from the root user. If "bufsize" is negative then, +because of type promotion, neither of the validation checks at the start +of the function are able to catch it: + + if (bufsize < sizeof(struct xfs_attrlist) || + bufsize > XFS_XATTR_LIST_MAX) + return -EINVAL; + +This means "bufsize" will trigger (WARN_ON_ONCE(size > INT_MAX)) in +kvmalloc_node(). Fix this by changing the type from int to size_t. + +Signed-off-by: Dan Carpenter +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_ioctl.c | 2 +- + fs/xfs/xfs_ioctl.h | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/fs/xfs/xfs_ioctl.c ++++ b/fs/xfs/xfs_ioctl.c +@@ -372,7 +372,7 @@ int + xfs_ioc_attr_list( + struct xfs_inode *dp, + void __user *ubuf, +- int bufsize, ++ size_t bufsize, + int flags, + struct xfs_attrlist_cursor __user *ucursor) + { +--- a/fs/xfs/xfs_ioctl.h ++++ b/fs/xfs/xfs_ioctl.h +@@ -38,8 +38,9 @@ xfs_readlink_by_handle( + int xfs_ioc_attrmulti_one(struct file *parfilp, struct inode *inode, + uint32_t opcode, void __user *uname, void __user *value, + uint32_t *len, uint32_t flags); +-int xfs_ioc_attr_list(struct xfs_inode *dp, void __user *ubuf, int bufsize, +- int flags, struct xfs_attrlist_cursor __user *ucursor); ++int xfs_ioc_attr_list(struct xfs_inode *dp, void __user *ubuf, ++ size_t bufsize, int flags, ++ struct xfs_attrlist_cursor __user *ucursor); + + extern struct dentry * + xfs_handle_to_dentry( diff --git a/queue-5.15/xfs-rename-the-next_agno-perag-iteration-variable.patch b/queue-5.15/xfs-rename-the-next_agno-perag-iteration-variable.patch new file mode 100644 index 00000000000..9bc7b606d20 --- /dev/null +++ b/queue-5.15/xfs-rename-the-next_agno-perag-iteration-variable.patch @@ -0,0 +1,62 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:07 -0700 +Subject: xfs: rename the next_agno perag iteration variable +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, Brian Foster , Dave Chinner , "Darrick J . Wong" , Leah Rumancik +Message-ID: <20220721213610.2794134-4-leah.rumancik@gmail.com> + +From: Brian Foster + +[ Upstream commit f1788b5e5ee25bedf00bb4d25f82b93820d61189 ] + +Rename the next_agno variable to be consistent across the several +iteration macros and shorten line length. + +[backport: dependency for 8ed004eb9d07a5d6114db3e97a166707c186262d] + +Signed-off-by: Brian Foster +Reviewed-by: Dave Chinner +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_ag.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/fs/xfs/libxfs/xfs_ag.h ++++ b/fs/xfs/libxfs/xfs_ag.h +@@ -127,22 +127,22 @@ void xfs_perag_put(struct xfs_perag *pag + static inline struct xfs_perag * + xfs_perag_next( + struct xfs_perag *pag, +- xfs_agnumber_t *next_agno) ++ xfs_agnumber_t *agno) + { + struct xfs_mount *mp = pag->pag_mount; + +- *next_agno = pag->pag_agno + 1; ++ *agno = pag->pag_agno + 1; + xfs_perag_put(pag); +- return xfs_perag_get(mp, *next_agno); ++ return xfs_perag_get(mp, *agno); + } + +-#define for_each_perag_range(mp, next_agno, end_agno, pag) \ +- for ((pag) = xfs_perag_get((mp), (next_agno)); \ +- (pag) != NULL && (next_agno) <= (end_agno); \ +- (pag) = xfs_perag_next((pag), &(next_agno))) ++#define for_each_perag_range(mp, agno, end_agno, pag) \ ++ for ((pag) = xfs_perag_get((mp), (agno)); \ ++ (pag) != NULL && (agno) <= (end_agno); \ ++ (pag) = xfs_perag_next((pag), &(agno))) + +-#define for_each_perag_from(mp, next_agno, pag) \ +- for_each_perag_range((mp), (next_agno), (mp)->m_sb.sb_agcount, (pag)) ++#define for_each_perag_from(mp, agno, pag) \ ++ for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount, (pag)) + + + #define for_each_perag(mp, agno, pag) \ diff --git a/queue-5.15/xfs-terminate-perag-iteration-reliably-on-agcount.patch b/queue-5.15/xfs-terminate-perag-iteration-reliably-on-agcount.patch new file mode 100644 index 00000000000..86d34265e31 --- /dev/null +++ b/queue-5.15/xfs-terminate-perag-iteration-reliably-on-agcount.patch @@ -0,0 +1,49 @@ +From foo@baz Sat Jul 23 05:23:15 PM CEST 2022 +From: Leah Rumancik +Date: Thu, 21 Jul 2022 14:36:08 -0700 +Subject: xfs: terminate perag iteration reliably on agcount +To: stable@vger.kernel.org, linux-xfs@vger.kernel.org +Cc: amir73il@gmail.com, Brian Foster , Dave Chinner , "Darrick J . Wong" , Leah Rumancik +Message-ID: <20220721213610.2794134-5-leah.rumancik@gmail.com> + +From: Brian Foster + +[ Upstream commit 8ed004eb9d07a5d6114db3e97a166707c186262d ] + +The for_each_perag_from() iteration macro relies on sb_agcount to +process every perag currently within EOFS from a given starting +point. It's perfectly valid to have perag structures beyond +sb_agcount, however, such as if a growfs is in progress. If a perag +loop happens to race with growfs in this manner, it will actually +attempt to process the post-EOFS perag where ->pag_agno == +sb_agcount. This is reproduced by xfs/104 and manifests as the +following assert failure in superblock write verifier context: + + XFS: Assertion failed: agno < mp->m_sb.sb_agcount, file: fs/xfs/libxfs/xfs_types.c, line: 22 + +Update the corresponding macro to only process perags that are +within the current sb_agcount. + +Fixes: 58d43a7e3263 ("xfs: pass perags around in fsmap data dev functions") +Signed-off-by: Brian Foster +Reviewed-by: Dave Chinner +Reviewed-by: Darrick J. Wong +Signed-off-by: Darrick J. Wong +Signed-off-by: Leah Rumancik +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_ag.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/xfs/libxfs/xfs_ag.h ++++ b/fs/xfs/libxfs/xfs_ag.h +@@ -142,7 +142,7 @@ xfs_perag_next( + (pag) = xfs_perag_next((pag), &(agno))) + + #define for_each_perag_from(mp, agno, pag) \ +- for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount, (pag)) ++ for_each_perag_range((mp), (agno), (mp)->m_sb.sb_agcount - 1, (pag)) + + + #define for_each_perag(mp, agno, pag) \ -- 2.47.3