[PATCH 1/2] ceph: clamp the inline data length in ceph_fill_inline_data()
From: Guanglei Zhu
Date: Tue Sep 08 2026 - 02:27:32 EST
The MDS decides how much inline data to attach to a reply, and the
client parses inline_len without any upper bound: ceph_decode_need()
only verifies that the message actually carries that many bytes.
ceph_fill_inline_data() then memcpy()s the data into a single page
with no length check, so a malicious or buggy MDS returning more than
one page of inline data makes the client write past the end of the
page it allocated.
Clamp the length to PAGE_SIZE so both callers, handle_cap_grant() and
fill_inode(), are covered.
Fixes: 31c542a199d7 ("ceph: add inline data to pagecache")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Guanglei Zhu <zhugl3@xxxxxxxxxxxx>
---
Tested in a QEMU guest with a hacked MDS that reports an 8k inline
payload for a 4k file: without the clamp the client overwrites the
page behind the inline page and page poisoning complains on the next
allocation; with it the data is truncated and a warning is logged.
fs/ceph/addr.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index e598b2d42..795cd1b9e 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2209,6 +2209,12 @@ void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
doutc(cl, "%p %llx.%llx len %zu locked_page %p\n", inode,
ceph_vinop(inode), len, locked_page);
+ if (len > PAGE_SIZE) {
+ pr_warn_ratelimited_client(cl, "oversized inline data %zu\n",
+ len);
+ len = PAGE_SIZE;
+ }
+
if (len > 0) {
void *kaddr = kmap_atomic(page);
memcpy(kaddr, data, len);
--
2.43.0