summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-14 10:18:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-14 10:18:06 -0700
commitc5890ac6d55c3d13e2d17817fec6676941ef08ee (patch)
tree1b943d277dca60ab99f85f5f651341b9187f4f85 /net
parentad8d485e665829ecbf3c97b22ce251f8ff5f8037 (diff)
parent91880e4a7fac45bc407771bc57bbaf4f37e9b4c3 (diff)
Merge tag 'ceph-for-7.2-rc8' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: "A handful of tiny fixes, with the main ones being a follow-up for CEPH_IOC_SET_LAYOUT{,_POLICY} ioctl permissions check that went into rc5 and a userspace compatibility fixup. The rest mostly harden against malformed network input. All marked for stable" * tag 'ceph-for-7.2-rc8' of https://github.com/ceph/ceph-client: ceph: use the mount idmap for the owner checks in the SET_LAYOUT ioctls ceph: fix MDS random selection readiness predicate libceph: Avoid using invalid osd indices from primary_temp libceph: fix OOB read in decode_watchers() via missing bounds check libceph: fix multiple unsafe decodes in decode_locker() libceph: tolerate addrvecs with multiple entries of the same type
Diffstat (limited to 'net')
-rw-r--r--net/ceph/cls_lock_client.c13
-rw-r--r--net/ceph/decode.c18
-rw-r--r--net/ceph/osd_client.c5
-rw-r--r--net/ceph/osdmap.c5
4 files changed, 25 insertions, 16 deletions
diff --git a/net/ceph/cls_lock_client.c b/net/ceph/cls_lock_client.c
index 377336982f7d..2c8fefc1a721 100644
--- a/net/ceph/cls_lock_client.c
+++ b/net/ceph/cls_lock_client.c
@@ -259,7 +259,8 @@ static int decode_locker(void **p, void *end, struct ceph_locker *locker)
if (ret)
return ret;
- ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name));
+ ceph_decode_copy_safe(p, end, &locker->id.name,
+ sizeof(locker->id.name), bad);
s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO);
if (IS_ERR(s))
return PTR_ERR(s);
@@ -270,19 +271,23 @@ static int decode_locker(void **p, void *end, struct ceph_locker *locker)
if (ret)
return ret;
- *p += sizeof(struct ceph_timespec); /* skip expiration */
+ /* skip expiration */
+ ceph_decode_skip_n(p, end, sizeof(struct ceph_timespec), bad);
ret = ceph_decode_entity_addr(p, end, &locker->info.addr);
if (ret)
return ret;
- len = ceph_decode_32(p);
- *p += len; /* skip description */
+ /* skip description */
+ ceph_decode_skip_string(p, end, bad);
dout("%s %s%llu cookie %s addr %s\n", __func__,
ENTITY_NAME(locker->id.name), locker->id.cookie,
ceph_pr_addr(&locker->info.addr));
return 0;
+
+bad:
+ return -EINVAL;
}
static int decode_lockers(void **p, void *end, u8 *type, char **tag,
diff --git a/net/ceph/decode.c b/net/ceph/decode.c
index bc109a1a4616..2f21af38cd9a 100644
--- a/net/ceph/decode.c
+++ b/net/ceph/decode.c
@@ -87,8 +87,9 @@ bad:
EXPORT_SYMBOL(ceph_decode_entity_addr);
/*
- * Return addr of desired type (MSGR2 or LEGACY) or error.
- * Make sure there is only one match.
+ * Return addr of desired type (MSGR2 or LEGACY) or error. In case of
+ * multiple matches, use the first one for compatibility with userspace
+ * messenger.
*
* Assume encoding with MSG_ADDR2.
*/
@@ -121,14 +122,13 @@ int ceph_decode_entity_addrvec(void **p, void *end, bool msgr2,
dout("%s i %d addr %s\n", __func__, i, ceph_pr_addr(&tmp_addr));
if (tmp_addr.type == my_type) {
- if (found) {
- pr_err("another match of type %d in addrvec\n",
- le32_to_cpu(my_type));
- return -EINVAL;
+ if (!found) {
+ memcpy(addr, &tmp_addr, sizeof(*addr));
+ found = true;
+ } else {
+ dout("%s skipping extra match of type %d in addrvec\n",
+ __func__, le32_to_cpu(my_type));
}
-
- memcpy(addr, &tmp_addr, sizeof(*addr));
- found = true;
}
}
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 2ff00070c181..28d76c2f6b3e 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -5030,7 +5030,7 @@ static int decode_watchers(void **p, void *end,
if (ret)
return ret;
- *num_watchers = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, *num_watchers, bad);
*watchers = kzalloc_objs(**watchers, *num_watchers, GFP_NOIO);
if (!*watchers)
return -ENOMEM;
@@ -5044,6 +5044,9 @@ static int decode_watchers(void **p, void *end,
}
return 0;
+
+bad:
+ return -EINVAL;
}
/*
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index a4b0dd8672ec..d6282f0bcff8 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -2809,9 +2809,10 @@ static void get_temp_osds(struct ceph_osdmap *osdmap,
}
}
- /* primary_temp? */
+ /* primary_temp? (shouldn't ever be a nonexistent or down OSD) */
pg = lookup_pg_mapping(&osdmap->primary_temp, pgid);
- if (pg)
+ if (pg && !WARN_ON_ONCE(ceph_osd_is_down(osdmap,
+ pg->primary_temp.osd)))
temp->primary = pg->primary_temp.osd;
}