summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2026-03-08 20:01:27 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-03-19 16:08:30 +0100
commitfc4d944dbaee92ab8d660e81e1469b4bb79f47f3 (patch)
tree3f6610649257b32d714f9d1097eb080858511aa6 /net
parentf9da5c1bbac5c8e33259fe00ed7347438fffa969 (diff)
libceph: reject preamble if control segment is empty
commit c4c22b846eceff05b1129b8844a80310e55a7f87 upstream. While head_onwire_len() has a branch to handle ctrl_len == 0 case, prepare_read_control() always sets up a kvec for the CRC meaning that a non-empty control segment is effectively assumed. All frames that clients deal with meet that assumption, so let's make it official and treat the preamble with an empty control segment as malformed. Cc: stable@vger.kernel.org Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Alex Markuze <amarkuze@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/ceph/messenger_v2.c17
1 files changed, 8 insertions, 9 deletions
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index b67f2b582bc7..9eabc57ccde4 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -392,7 +392,7 @@ static int head_onwire_len(int ctrl_len, bool secure)
int head_len;
int rem_len;
- BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN);
+ BUG_ON(ctrl_len < 1 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN);
if (secure) {
head_len = CEPH_PREAMBLE_SECURE_LEN;
@@ -401,9 +401,7 @@ static int head_onwire_len(int ctrl_len, bool secure)
head_len += padded_len(rem_len) + CEPH_GCM_TAG_LEN;
}
} else {
- head_len = CEPH_PREAMBLE_PLAIN_LEN;
- if (ctrl_len)
- head_len += ctrl_len + CEPH_CRC_LEN;
+ head_len = CEPH_PREAMBLE_PLAIN_LEN + ctrl_len + CEPH_CRC_LEN;
}
return head_len;
}
@@ -528,11 +526,16 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc)
desc->fd_aligns[i] = ceph_decode_16(&p);
}
- if (desc->fd_lens[0] < 0 ||
+ /*
+ * This would fire for FRAME_TAG_WAIT (it has one empty
+ * segment), but we should never get it as client.
+ */
+ if (desc->fd_lens[0] < 1 ||
desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) {
pr_err("bad control segment length %d\n", desc->fd_lens[0]);
return -EINVAL;
}
+
if (desc->fd_lens[1] < 0 ||
desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
pr_err("bad front segment length %d\n", desc->fd_lens[1]);
@@ -549,10 +552,6 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc)
return -EINVAL;
}
- /*
- * This would fire for FRAME_TAG_WAIT (it has one empty
- * segment), but we should never get it as client.
- */
if (!desc->fd_lens[desc->fd_seg_cnt - 1]) {
pr_err("last segment empty, segment count %d\n",
desc->fd_seg_cnt);