[PATCH 2/2] ceph: fix out-of-bounds read in ceph_netfs_issue_op_inline()

From: Guanglei Zhu

Date: Tue Sep 08 2026 - 02:26:55 EST


The read offset is validated against i_size but never against
inline_len, and the two fields come from the MDS independently. When
a read starts past the end of the inline data, the subtraction

len = min_t(size_t, iinfo->inline_len - subreq->start, subreq->len);

underflows and min_t() ends up with subreq->len, so copy_to_iter()
reads past the end of the inline buffer straight into the user
buffer. A malicious or buggy MDS reporting a short inline payload
together with an inflated i_size can thus leak kernel heap memory to
userspace.

Bail out when the offset is not within the inline data. The subreq
then completes short without progress and the read fails with
-ENODATA.

Fixes: 5b19f1eba459 ("ceph: make ceph_netfs_issue_op() handle inlined data")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Guanglei Zhu <zhugl3@xxxxxxxxxxxx>
---

Verified with a fault injector on the reply decoding path that
makes the MDS report a short inline payload with an inflated i_size:
the unpatched client trips HARDENED_USERCOPY on a read past the end
of the reply buffer, with the check the read fails with -ENODATA.
fs/ceph/addr.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 795cd1b9e..0db807abc 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -322,6 +322,11 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
return false;
}

+ if (subreq->start >= iinfo->inline_len) {
+ ceph_mdsc_put_request(req);
+ goto out;
+ }
+
len = min_t(size_t, iinfo->inline_len - subreq->start, subreq->len);
err = copy_to_iter(iinfo->inline_data + subreq->start, len, &subreq->io_iter);
if (err == 0) {
--
2.43.0