7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: sung byeongchan [ Upstream commit 166375898d29fea050a9abec855da6075050d5c9 ] __build_xattrs() advances over an MDS-provided name length before checking that the name remains in the encoded xattr blob. On 32-bit clients, UINT_MAX wraps the cursor and is stored as a negative internal name length. A later ordinary listxattr() converts it back to a UINT_MAX memcpy size and corrupts kernel memory. Check the name range before advancing and reject name, value, or aggregate sizes that overflow the signed internal accounting. The malformed blob corrupted kernel state in two baseline boots. It was rejected cleanly twice with this change, while normal and length-only controls remained safe. Cc: stable@vger.kernel.org Fixes: 355da1eb7a1f ("ceph: inode operations") Assisted-by: LLM Signed-off-by: sung byeongchan Reviewed-by: Alex Markuze Signed-off-by: Ilya Dryomov Signed-off-by: Sasha Levin --- fs/ceph/xattr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index cc4ffbbcb719a..ff70e4df9331c 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -11,6 +11,7 @@ #include #include #include +#include #define XATTR_CEPH_PREFIX "ceph." #define XATTR_CEPH_PREFIX_LEN (sizeof (XATTR_CEPH_PREFIX) - 1) @@ -843,14 +844,23 @@ static int __build_xattrs(struct inode *inode) } err = -EIO; while (numattr--) { + int names_size, vals_size; + ceph_decode_32_safe(&p, end, len, bad); namelen = len; name = p; + ceph_decode_need(&p, end, namelen, bad); p += len; ceph_decode_32_safe(&p, end, len, bad); ceph_decode_need(&p, end, len, bad); val = p; p += len; + if (namelen > INT_MAX || len > INT_MAX || + check_add_overflow(ci->i_xattrs.names_size, + (int)namelen, &names_size) || + check_add_overflow(ci->i_xattrs.vals_size, + (int)len, &vals_size)) + goto bad; err = __set_xattr(ci, name, namelen, val, len, 0, 0, &xattrs[numattr]); -- 2.53.0