Commit ddbd9161 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ceph-for-6.5-rc2' of https://github.com/ceph/ceph-client

Pull ceph fix from Ilya Dryomov:
 "A fix to prevent a potential buffer overrun in the messenger, marked
  for stable"

* tag 'ceph-for-6.5-rc2' of https://github.com/ceph/ceph-client:
  libceph: harden msgr2.1 frame segment length checks
parents 4b810bf0 a282a2f1
Loading
Loading
Loading
Loading
+26 −15
Original line number Diff line number Diff line
@@ -390,6 +390,8 @@ 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);

	if (secure) {
		head_len = CEPH_PREAMBLE_SECURE_LEN;
		if (ctrl_len > CEPH_PREAMBLE_INLINE_LEN) {
@@ -408,6 +410,10 @@ static int head_onwire_len(int ctrl_len, bool secure)
static int __tail_onwire_len(int front_len, int middle_len, int data_len,
			     bool secure)
{
	BUG_ON(front_len < 0 || front_len > CEPH_MSG_MAX_FRONT_LEN ||
	       middle_len < 0 || middle_len > CEPH_MSG_MAX_MIDDLE_LEN ||
	       data_len < 0 || data_len > CEPH_MSG_MAX_DATA_LEN);

	if (!front_len && !middle_len && !data_len)
		return 0;

@@ -520,29 +526,34 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc)
		desc->fd_aligns[i] = ceph_decode_16(&p);
	}

	/*
	 * 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\n");
	if (desc->fd_lens[0] < 0 ||
	    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[0] > CEPH_MSG_MAX_CONTROL_LEN) {
		pr_err("control segment too big %d\n", desc->fd_lens[0]);
	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]);
		return -EINVAL;
	}
	if (desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
		pr_err("front segment too big %d\n", desc->fd_lens[1]);
	if (desc->fd_lens[2] < 0 ||
	    desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
		pr_err("bad middle segment length %d\n", desc->fd_lens[2]);
		return -EINVAL;
	}
	if (desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
		pr_err("middle segment too big %d\n", desc->fd_lens[2]);
	if (desc->fd_lens[3] < 0 ||
	    desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
		pr_err("bad data segment length %d\n", desc->fd_lens[3]);
		return -EINVAL;
	}
	if (desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
		pr_err("data segment too big %d\n", desc->fd_lens[3]);

	/*
	 * 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);
		return -EINVAL;
	}