7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: sung byeongchan [ Upstream commit 8cab7e7461f81ea1e0fd45082b50bb3c04c0bb10 ] parse_reply_info_in() advances over the fragtree split array using an unchecked count multiplication. On a 32-bit client, nsplits=0x20000000 wraps the byte length to zero, so the reply is accepted and ceph_fill_fragtree() sorts far beyond the message front. Compute the split length with size_mul() and require the complete array to remain in the inode record before advancing the cursor. The malformed reply faulted in frag_tree_split_cmp() twice on the tested i386 baseline. It was rejected without a fault twice after this change, while a normal reply and a one-split control remained functional. Cc: stable@vger.kernel.org Fixes: 2f2dc053404f ("ceph: MDS client") Assisted-by: LLM Signed-off-by: sung byeongchan Reviewed-by: Alex Markuze Signed-off-by: Ilya Dryomov Signed-off-by: Sasha Levin --- fs/ceph/mds_client.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index b354c3296de36..1806cdc202718 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "super.h" #include "mds_client.h" @@ -120,6 +121,7 @@ static int parse_reply_info_in(void **p, void *end, struct ceph_mds_client *mdsc) { int err = 0; + size_t splits_len; u8 struct_v = 0; u8 struct_compat = 0; u32 struct_len = 0; @@ -140,9 +142,11 @@ static int parse_reply_info_in(void **p, void *end, ceph_decode_need(p, end, sizeof(struct ceph_mds_reply_inode), bad); info->in = *p; - *p += sizeof(struct ceph_mds_reply_inode) + - sizeof(*info->in->fragtree.splits) * - le32_to_cpu(info->in->fragtree.nsplits); + splits_len = size_mul(sizeof(*info->in->fragtree.splits), + le32_to_cpu(info->in->fragtree.nsplits)); + *p += sizeof(struct ceph_mds_reply_inode); + ceph_decode_need(p, end, splits_len, bad); + *p += splits_len; ceph_decode_32_safe(p, end, info->symlink_len, bad); ceph_decode_need(p, end, info->symlink_len, bad); -- 2.53.0