Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libceph: fail sparse-read if the data length doesn't match

Once this happens that means there have bugs.

Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

authored by

Xiubo Li and committed by
Ilya Dryomov
cd7d469c 54be6c6c

+17 -4
+2 -1
include/linux/ceph/osd_client.h
··· 45 45 CEPH_SPARSE_READ_HDR = 0, 46 46 CEPH_SPARSE_READ_EXTENTS, 47 47 CEPH_SPARSE_READ_DATA_LEN, 48 + CEPH_SPARSE_READ_DATA_PRE, 48 49 CEPH_SPARSE_READ_DATA, 49 50 }; 50 51 ··· 65 64 u64 sr_req_len; /* orig request length */ 66 65 u64 sr_pos; /* current pos in buffer */ 67 66 int sr_index; /* current extent index */ 68 - __le32 sr_datalen; /* length of actual data */ 67 + u32 sr_datalen; /* length of actual data */ 69 68 u32 sr_count; /* extent count in reply */ 70 69 int sr_ext_len; /* length of extent array */ 71 70 struct ceph_sparse_extent *sr_extent; /* extent array */
+15 -3
net/ceph/osd_client.c
··· 5857 5857 struct ceph_osd *o = con->private; 5858 5858 struct ceph_sparse_read *sr = &o->o_sparse_read; 5859 5859 u32 count = sr->sr_count; 5860 - u64 eoff, elen; 5861 - int ret; 5860 + u64 eoff, elen, len = 0; 5861 + int i, ret; 5862 5862 5863 5863 switch (sr->sr_state) { 5864 5864 case CEPH_SPARSE_READ_HDR: ··· 5903 5903 convert_extent_map(sr); 5904 5904 ret = sizeof(sr->sr_datalen); 5905 5905 *pbuf = (char *)&sr->sr_datalen; 5906 - sr->sr_state = CEPH_SPARSE_READ_DATA; 5906 + sr->sr_state = CEPH_SPARSE_READ_DATA_PRE; 5907 5907 break; 5908 + case CEPH_SPARSE_READ_DATA_PRE: 5909 + /* Convert sr_datalen to host-endian */ 5910 + sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen); 5911 + for (i = 0; i < count; i++) 5912 + len += sr->sr_extent[i].len; 5913 + if (sr->sr_datalen != len) { 5914 + pr_warn_ratelimited("data len %u != extent len %llu\n", 5915 + sr->sr_datalen, len); 5916 + return -EREMOTEIO; 5917 + } 5918 + sr->sr_state = CEPH_SPARSE_READ_DATA; 5919 + fallthrough; 5908 5920 case CEPH_SPARSE_READ_DATA: 5909 5921 if (sr->sr_index >= count) { 5910 5922 sr->sr_state = CEPH_SPARSE_READ_HDR;