All of lore.kernel.org
 help / color / mirror / Atom feed
From: Max Kellermann <max.kellermann@ionos.com>
To: xiubli@redhat.com, idryomov@gmail.com, amarkuze@redhat.com,
	ceph-devel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Max Kellermann <max.kellermann@ionos.com>, stable@vger.kernel.org
Subject: [PATCH 3/9] ceph: fix mdsmap use-after-free in __ceph_setxattr()
Date: Wed, 11 Nov 2026 17:18:24 +0100	[thread overview]
Message-ID: <20261111161830.1336485-4-max.kellermann@ionos.com> (raw)
In-Reply-To: <20261111161830.1336485-1-max.kellermann@ionos.com>

__ceph_setxattr() reads mdsc->mdsmap->m_max_xattr_size while holding
only ci->i_ceph_lock, but ceph_mdsc_handle_mdsmap() replaces the
mdsmap and frees the old one under mdsc->mutex.  A setxattr() racing
with an mdsmap update can therefore read freed memory.

mdsc->mutex cannot be taken under i_ceph_lock, so keep a copy of the
limit in struct ceph_mds_client, updated by ceph_mdsc_handle_mdsmap()
under the mutex, and read that instead.

Fixes: d93231a6bc8a ("ceph: prevent a client from exceeding the MDS maximum xattr size")
Cc: stable@vger.kernel.org
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
 fs/ceph/mds_client.c |  1 +
 fs/ceph/mds_client.h |  7 +++++++
 fs/ceph/xattr.c      | 10 ++++++----
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 15df9d22008d..da40f2cb80f2 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -7247,6 +7247,7 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
 	} else {
 		mdsc->mdsmap = newmap;  /* first mds map */
 	}
+	WRITE_ONCE(mdsc->max_xattr_size, mdsc->mdsmap->m_max_xattr_size);
 	mdsc->fsc->max_file_size = min((loff_t)mdsc->mdsmap->m_max_file_size,
 					MAX_LFS_FILESIZE);
 
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index ff9ba09f3b59..bd97f73ede20 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -495,6 +495,13 @@ struct ceph_mds_client {
 	struct mutex            mutex;         /* all nested structures */
 
 	struct ceph_mdsmap      *mdsmap;
+
+	/*
+	 * Copy of mdsmap->m_max_xattr_size for readers that cannot take
+	 * the mutex; updated by ceph_mdsc_handle_mdsmap().
+	 */
+	u64			max_xattr_size;
+
 	struct completion       safe_umount_waiters;
 	wait_queue_head_t       session_close_wq;
 	struct list_head        waiting_for_map;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index c6085191c29a..8f97b6448d7a 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1211,6 +1211,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
 	struct ceph_mds_client *mdsc = fsc->mdsc;
 	struct ceph_cap_flush *prealloc_cf = NULL;
 	struct ceph_buffer *old_blob = NULL;
+	u64 max_xattr_size;
 	int issued;
 	int err;
 	int dirty = 0;
@@ -1260,13 +1261,14 @@ int __ceph_setxattr(struct inode *inode, const char *name,
 
 	spin_lock(&ci->i_ceph_lock);
 retry:
+	max_xattr_size = READ_ONCE(mdsc->max_xattr_size);
 	issued = __ceph_caps_issued(ci, NULL);
 	required_blob_size = __get_required_blob_size(ci, name_len, val_len);
 	if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) ||
-	    (required_blob_size > mdsc->mdsmap->m_max_xattr_size)) {
+	    (required_blob_size > max_xattr_size)) {
 		boutc(cl, "sync version: %llu size: %d max: %llu\n",
 		      ci->i_xattrs.version, required_blob_size,
-		      mdsc->mdsmap->m_max_xattr_size);
+		      max_xattr_size);
 		goto do_sync;
 	}
 
@@ -1294,9 +1296,9 @@ int __ceph_setxattr(struct inode *inode, const char *name,
 	 * prealloc_blob size check below reflects the current tree state.
 	 */
 	required_blob_size = __get_required_blob_size(ci, name_len, val_len);
-	if (required_blob_size > mdsc->mdsmap->m_max_xattr_size) {
+	if (required_blob_size > max_xattr_size) {
 		boutc(cl, "sync (size too large): %d > %llu\n",
-		      required_blob_size, mdsc->mdsmap->m_max_xattr_size);
+		      required_blob_size, max_xattr_size);
 		goto do_sync;
 	}
 
-- 
2.53.0


  parent reply	other threads:[~2026-11-11 16:18 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11 16:18 [PATCH 0/9] ceph: fix mdsmap and osdmap use-after-free in unlocked readers Max Kellermann
2026-11-11 16:18 ` [PATCH 1/9] ceph: fix mdsmap use-after-free in ceph_statfs() Max Kellermann
2026-11-11 16:18 ` [PATCH 2/9] ceph: fix mdsmap use-after-free in debugfs mdsmap_show() Max Kellermann
2026-11-11 16:18 ` Max Kellermann [this message]
2026-11-11 16:18 ` [PATCH 4/9] ceph: fix mdsmap use-after-free in send_renew_caps() and renewed_caps() Max Kellermann
2026-11-11 16:18 ` [PATCH 5/9] ceph: fix mdsmap use-after-free in mds_peer_reset() Max Kellermann
2026-11-11 16:18 ` [PATCH 6/9] ceph: fix mdsmap use-after-free in ceph_get_tree() error path Max Kellermann
2026-11-11 16:18 ` [PATCH 7/9] ceph: fix osdmap use-after-free in ceph_sync_setxattr() Max Kellermann
2026-11-11 16:18 ` [PATCH 8/9] libceph: fix osdmap use-after-free in ceph_wait_for_latest_osdmap() Max Kellermann
2026-11-11 16:18 ` [PATCH 9/9] rbd: fix osdmap use-after-free in pool lookups Max Kellermann
2026-11-12 14:48 ` [PATCH 0/9] ceph: fix mdsmap and osdmap use-after-free in unlocked readers Xiubo Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261111161830.1336485-4-max.kellermann@ionos.com \
    --to=max.kellermann@ionos.com \
    --cc=amarkuze@redhat.com \
    --cc=ceph-devel@vger.kernel.org \
    --cc=idryomov@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=xiubli@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.