]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 31 Mar 2026 13:12:15 +0000 (15:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 31 Mar 2026 13:12:15 +0000 (15:12 +0200)
added patches:
erofs-fix-bug-bad-page-state-in-z_erofs_do_read_page.patch
mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch
xfs-avoid-dereferencing-log-items-after-push-callbacks.patch
xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch

queue-6.6/erofs-fix-bug-bad-page-state-in-z_erofs_do_read_page.patch [new file with mode: 0644]
queue-6.6/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch [new file with mode: 0644]
queue-6.6/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch [new file with mode: 0644]

diff --git a/queue-6.6/erofs-fix-bug-bad-page-state-in-z_erofs_do_read_page.patch b/queue-6.6/erofs-fix-bug-bad-page-state-in-z_erofs_do_read_page.patch
new file mode 100644 (file)
index 0000000..e25ccfb
--- /dev/null
@@ -0,0 +1,41 @@
+From hsiangkao@linux.alibaba.com Fri Mar 27 05:15:33 2026
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+Date: Fri, 27 Mar 2026 12:15:24 +0800
+Subject: erofs: fix "BUG: Bad page state in z_erofs_do_read_page"
+To: stable@vger.kernel.org, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-erofs@lists.ozlabs.org, Gao Xiang <hsiangkao@linux.alibaba.com>, syzbot+b6353e35ae2bab997538@syzkaller.appspotmail.com
+Message-ID: <20260327041524.1087336-1-hsiangkao@linux.alibaba.com>
+
+From: Gao Xiang <hsiangkao@linux.alibaba.com>
+
+It's actually a stable-only issue from backporting 9e2f9d34dd12
+("erofs: handle overlapped pclusters out of crafted images properly")
+
+We missed to update `oldpage` after `pcl->compressed_bvecs[nr].page`
+is updated, so that the following cmpxchg() will fail; the original
+upstream commit doesn't behave like this due to new features and
+refactoring.
+
+This backport issue only impacts some specific crafted images and
+normal filesystems won't be impacted at all.
+
+Fixes: 1bf7e414cac3 ("erofs: handle overlapped pclusters out of crafted images properly") # 6.6.y
+Closes: https://syzkaller.appspot.com/bug?extid=b6353e35ae2bab997538
+Reported-and-tested-by: syzbot+b6353e35ae2bab997538@syzkaller.appspotmail.com [1]
+[1] https://lore.kernel.org/r/69c3b299.a70a0220.234938.004b.GAE@google.com
+Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/erofs/zdata.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/erofs/zdata.c
++++ b/fs/erofs/zdata.c
+@@ -1503,6 +1503,7 @@ repeat:
+       lock_page(page);
+       if (likely(page->mapping == mc)) {
+               WRITE_ONCE(pcl->compressed_bvecs[nr].page, page);
++              oldpage = page;
+               /*
+                * The cached folio is still in managed cache but without
diff --git a/queue-6.6/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch b/queue-6.6/mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch
new file mode 100644 (file)
index 0000000..45e7568
--- /dev/null
@@ -0,0 +1,59 @@
+From 1bfe9fb5ed2667fb075682408b776b5273162615 Mon Sep 17 00:00:00 2001
+From: Josh Law <objecting@objecting.org>
+Date: Sat, 21 Mar 2026 10:54:25 -0700
+Subject: mm/damon/sysfs: check contexts->nr before accessing contexts_arr[0]
+
+From: Josh Law <objecting@objecting.org>
+
+commit 1bfe9fb5ed2667fb075682408b776b5273162615 upstream.
+
+Multiple sysfs command paths dereference contexts_arr[0] without first
+verifying that kdamond->contexts->nr == 1.  A user can set nr_contexts to
+0 via sysfs while DAMON is running, causing NULL pointer dereferences.
+
+In more detail, the issue can be triggered by privileged users like
+below.
+
+First, start DAMON and make contexts directory empty
+(kdamond->contexts->nr == 0).
+
+    # damo start
+    # cd /sys/kernel/mm/damon/admin/kdamonds/0
+    # echo 0 > contexts/nr_contexts
+
+Then, each of below commands will cause the NULL pointer dereference.
+
+    # echo update_schemes_stats > state
+    # echo update_schemes_tried_regions > state
+    # echo update_schemes_tried_bytes > state
+    # echo update_schemes_effective_quotas > state
+    # echo update_tuned_intervals > state
+
+Guard all commands (except OFF) at the entry point of
+damon_sysfs_handle_cmd().
+
+Link: https://lkml.kernel.org/r/20260321175427.86000-3-sj@kernel.org
+Fixes: 0ac32b8affb5 ("mm/damon/sysfs: support DAMOS stats")
+Signed-off-by: Josh Law <objecting@objecting.org>
+Reviewed-by: SeongJae Park <sj@kernel.org>
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org>   [5.18+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/sysfs.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/mm/damon/sysfs.c
++++ b/mm/damon/sysfs.c
+@@ -1494,6 +1494,9 @@ static int damon_sysfs_handle_cmd(enum d
+ {
+       bool need_wait = true;
++      if (cmd != DAMON_SYSFS_CMD_OFF && kdamond->contexts->nr != 1)
++              return -EINVAL;
++
+       /* Handle commands that doesn't access DAMON context-internal data */
+       switch (cmd) {
+       case DAMON_SYSFS_CMD_ON:
index 40f4ecb91297c8d269c8101f28144b2b845415f1..a5bcf8c509229e5a4e53e5d942a3149d401aa955 100644 (file)
@@ -153,3 +153,7 @@ gfs2-fix-unlikely-race-in-gdlm_put_lock.patch
 libbpf-fix-wdiscarded-qualifiers-under-c23.patch
 xattr-switch-to-class-fd.patch
 nvme-fix-admin-queue-leak-on-controller-reset.patch
+mm-damon-sysfs-check-contexts-nr-before-accessing-contexts_arr.patch
+xfs-avoid-dereferencing-log-items-after-push-callbacks.patch
+xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch
+erofs-fix-bug-bad-page-state-in-z_erofs_do_read_page.patch
diff --git a/queue-6.6/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch b/queue-6.6/xfs-avoid-dereferencing-log-items-after-push-callbacks.patch
new file mode 100644 (file)
index 0000000..be4d805
--- /dev/null
@@ -0,0 +1,172 @@
+From 79ef34ec0554ec04bdbafafbc9836423734e1bd6 Mon Sep 17 00:00:00 2001
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+Date: Tue, 10 Mar 2026 18:38:38 +0000
+Subject: xfs: avoid dereferencing log items after push callbacks
+
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+
+commit 79ef34ec0554ec04bdbafafbc9836423734e1bd6 upstream.
+
+After xfsaild_push_item() calls iop_push(), the log item may have been
+freed if the AIL lock was dropped during the push. Background inode
+reclaim or the dquot shrinker can free the log item while the AIL lock
+is not held, and the tracepoints in the switch statement dereference
+the log item after iop_push() returns.
+
+Fix this by capturing the log item type, flags, and LSN before calling
+xfsaild_push_item(), and introducing a new xfs_ail_push_class trace
+event class that takes these pre-captured values and the ailp pointer
+instead of the log item pointer.
+
+Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c
+Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary")
+Cc: stable@vger.kernel.org # v5.9
+Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_trace.c     |    1 +
+ fs/xfs/xfs_trace.h     |   36 ++++++++++++++++++++++++++++++++----
+ fs/xfs/xfs_trans_ail.c |   26 +++++++++++++++++++-------
+ 3 files changed, 52 insertions(+), 11 deletions(-)
+
+--- a/fs/xfs/xfs_trace.c
++++ b/fs/xfs/xfs_trace.c
+@@ -22,6 +22,7 @@
+ #include "xfs_trans.h"
+ #include "xfs_log.h"
+ #include "xfs_log_priv.h"
++#include "xfs_trans_priv.h"
+ #include "xfs_buf_item.h"
+ #include "xfs_quota.h"
+ #include "xfs_dquot_item.h"
+--- a/fs/xfs/xfs_trace.h
++++ b/fs/xfs/xfs_trace.h
+@@ -50,6 +50,7 @@
+ #include <linux/tracepoint.h>
+ struct xfs_agf;
++struct xfs_ail;
+ struct xfs_alloc_arg;
+ struct xfs_attr_list_context;
+ struct xfs_buf_log_item;
+@@ -1332,14 +1333,41 @@ TRACE_EVENT(xfs_log_force,
+ DEFINE_EVENT(xfs_log_item_class, name, \
+       TP_PROTO(struct xfs_log_item *lip), \
+       TP_ARGS(lip))
+-DEFINE_LOG_ITEM_EVENT(xfs_ail_push);
+-DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned);
+-DEFINE_LOG_ITEM_EVENT(xfs_ail_locked);
+-DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing);
+ DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark);
+ DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip);
+ DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin);
++DECLARE_EVENT_CLASS(xfs_ail_push_class,
++      TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn),
++      TP_ARGS(ailp, type, flags, lsn),
++      TP_STRUCT__entry(
++              __field(dev_t, dev)
++              __field(uint, type)
++              __field(unsigned long, flags)
++              __field(xfs_lsn_t, lsn)
++      ),
++      TP_fast_assign(
++              __entry->dev = ailp->ail_log->l_mp->m_super->s_dev;
++              __entry->type = type;
++              __entry->flags = flags;
++              __entry->lsn = lsn;
++      ),
++      TP_printk("dev %d:%d lsn %d/%d type %s flags %s",
++                MAJOR(__entry->dev), MINOR(__entry->dev),
++                CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn),
++                __print_symbolic(__entry->type, XFS_LI_TYPE_DESC),
++                __print_flags(__entry->flags, "|", XFS_LI_FLAGS))
++)
++
++#define DEFINE_AIL_PUSH_EVENT(name) \
++DEFINE_EVENT(xfs_ail_push_class, name, \
++      TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), \
++      TP_ARGS(ailp, type, flags, lsn))
++DEFINE_AIL_PUSH_EVENT(xfs_ail_push);
++DEFINE_AIL_PUSH_EVENT(xfs_ail_pinned);
++DEFINE_AIL_PUSH_EVENT(xfs_ail_locked);
++DEFINE_AIL_PUSH_EVENT(xfs_ail_flushing);
++
+ DECLARE_EVENT_CLASS(xfs_ail_class,
+       TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn),
+       TP_ARGS(lip, old_lsn, new_lsn),
+--- a/fs/xfs/xfs_trans_ail.c
++++ b/fs/xfs/xfs_trans_ail.c
+@@ -389,6 +389,12 @@ xfsaild_resubmit_item(
+       return XFS_ITEM_SUCCESS;
+ }
++/*
++ * Push a single log item from the AIL.
++ *
++ * @lip may have been released and freed by the time this function returns,
++ * so callers must not dereference the log item afterwards.
++ */
+ static inline uint
+ xfsaild_push_item(
+       struct xfs_ail          *ailp,
+@@ -476,20 +482,26 @@ xfsaild_push(
+       lsn = lip->li_lsn;
+       while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) {
+-              int     lock_result;
++              int             lock_result;
++              uint            type = lip->li_type;
++              unsigned long   flags = lip->li_flags;
++              xfs_lsn_t       item_lsn = lip->li_lsn;
+               /*
+                * Note that iop_push may unlock and reacquire the AIL lock.  We
+                * rely on the AIL cursor implementation to be able to deal with
+                * the dropped lock.
++               *
++               * The log item may have been freed by the push, so it must not
++               * be accessed or dereferenced below this line.
+                */
+               lock_result = xfsaild_push_item(ailp, lip);
+               switch (lock_result) {
+               case XFS_ITEM_SUCCESS:
+                       XFS_STATS_INC(mp, xs_push_ail_success);
+-                      trace_xfs_ail_push(lip);
++                      trace_xfs_ail_push(ailp, type, flags, item_lsn);
+-                      ailp->ail_last_pushed_lsn = lsn;
++                      ailp->ail_last_pushed_lsn = item_lsn;
+                       break;
+               case XFS_ITEM_FLUSHING:
+@@ -505,22 +517,22 @@ xfsaild_push(
+                        * AIL is being flushed.
+                        */
+                       XFS_STATS_INC(mp, xs_push_ail_flushing);
+-                      trace_xfs_ail_flushing(lip);
++                      trace_xfs_ail_flushing(ailp, type, flags, item_lsn);
+                       flushing++;
+-                      ailp->ail_last_pushed_lsn = lsn;
++                      ailp->ail_last_pushed_lsn = item_lsn;
+                       break;
+               case XFS_ITEM_PINNED:
+                       XFS_STATS_INC(mp, xs_push_ail_pinned);
+-                      trace_xfs_ail_pinned(lip);
++                      trace_xfs_ail_pinned(ailp, type, flags, item_lsn);
+                       stuck++;
+                       ailp->ail_log_flush++;
+                       break;
+               case XFS_ITEM_LOCKED:
+                       XFS_STATS_INC(mp, xs_push_ail_locked);
+-                      trace_xfs_ail_locked(lip);
++                      trace_xfs_ail_locked(ailp, type, flags, item_lsn);
+                       stuck++;
+                       break;
diff --git a/queue-6.6/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch b/queue-6.6/xfs-save-ailp-before-dropping-the-ail-lock-in-push-callbacks.patch
new file mode 100644 (file)
index 0000000..b2f8569
--- /dev/null
@@ -0,0 +1,96 @@
+From 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 Mon Sep 17 00:00:00 2001
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+Date: Tue, 10 Mar 2026 18:38:39 +0000
+Subject: xfs: save ailp before dropping the AIL lock in push callbacks
+
+From: Yuto Ohnuki <ytohnuki@amazon.com>
+
+commit 394d70b86fae9fe865e7e6d9540b7696f73aa9b6 upstream.
+
+In xfs_inode_item_push() and xfs_qm_dquot_logitem_push(), the AIL lock
+is dropped to perform buffer IO. Once the cluster buffer no longer
+protects the log item from reclaim, the log item may be freed by
+background reclaim or the dquot shrinker. The subsequent spin_lock()
+call dereferences lip->li_ailp, which is a use-after-free.
+
+Fix this by saving the ailp pointer in a local variable while the AIL
+lock is held and the log item is guaranteed to be valid.
+
+Reported-by: syzbot+652af2b3c5569c4ab63c@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=652af2b3c5569c4ab63c
+Fixes: 90c60e164012 ("xfs: xfs_iflush() is no longer necessary")
+Cc: stable@vger.kernel.org # v5.9
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_dquot_item.c |    9 +++++++--
+ fs/xfs/xfs_inode_item.c |    9 +++++++--
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/fs/xfs/xfs_dquot_item.c
++++ b/fs/xfs/xfs_dquot_item.c
+@@ -125,6 +125,7 @@ xfs_qm_dquot_logitem_push(
+ {
+       struct xfs_dquot        *dqp = DQUOT_ITEM(lip)->qli_dquot;
+       struct xfs_buf          *bp = lip->li_buf;
++      struct xfs_ail          *ailp = lip->li_ailp;
+       uint                    rval = XFS_ITEM_SUCCESS;
+       int                     error;
+@@ -153,7 +154,7 @@ xfs_qm_dquot_logitem_push(
+               goto out_unlock;
+       }
+-      spin_unlock(&lip->li_ailp->ail_lock);
++      spin_unlock(&ailp->ail_lock);
+       error = xfs_qm_dqflush(dqp, &bp);
+       if (!error) {
+@@ -163,7 +164,11 @@ xfs_qm_dquot_logitem_push(
+       } else if (error == -EAGAIN)
+               rval = XFS_ITEM_LOCKED;
+-      spin_lock(&lip->li_ailp->ail_lock);
++      /*
++       * The buffer no longer protects the log item from reclaim, so
++       * do not reference lip after this point.
++       */
++      spin_lock(&ailp->ail_lock);
+ out_unlock:
+       xfs_dqunlock(dqp);
+       return rval;
+--- a/fs/xfs/xfs_inode_item.c
++++ b/fs/xfs/xfs_inode_item.c
+@@ -727,6 +727,7 @@ xfs_inode_item_push(
+       struct xfs_inode_log_item *iip = INODE_ITEM(lip);
+       struct xfs_inode        *ip = iip->ili_inode;
+       struct xfs_buf          *bp = lip->li_buf;
++      struct xfs_ail          *ailp = lip->li_ailp;
+       uint                    rval = XFS_ITEM_SUCCESS;
+       int                     error;
+@@ -749,7 +750,7 @@ xfs_inode_item_push(
+       if (!xfs_buf_trylock(bp))
+               return XFS_ITEM_LOCKED;
+-      spin_unlock(&lip->li_ailp->ail_lock);
++      spin_unlock(&ailp->ail_lock);
+       /*
+        * We need to hold a reference for flushing the cluster buffer as it may
+@@ -773,7 +774,11 @@ xfs_inode_item_push(
+               rval = XFS_ITEM_LOCKED;
+       }
+-      spin_lock(&lip->li_ailp->ail_lock);
++      /*
++       * The buffer no longer protects the log item from reclaim, so
++       * do not reference lip after this point.
++       */
++      spin_lock(&ailp->ail_lock);
+       return rval;
+ }