Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc255c76 authored by Ilya Dryomov's avatar Ilya Dryomov
Browse files

libceph: implement CEPHX_V2 calculation mode

Derive the signature from the entire buffer (both AES cipher blocks)
instead of using just the first half of the first block, leaving out
data_crc entirely.

This addresses CVE-2018-1129.

Link: http://tracker.ceph.com/issues/24837


Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Reviewed-by: default avatarSage Weil <sage@redhat.com>
parent 6daca13d
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -165,9 +165,9 @@ DEFINE_CEPH_FEATURE(58, 1, FS_FILE_LAYOUT_V2) // overlap
DEFINE_CEPH_FEATURE(59, 1, FS_BTIME)
DEFINE_CEPH_FEATURE(59, 1, FS_CHANGE_ATTR) // overlap
DEFINE_CEPH_FEATURE(59, 1, MSG_ADDR2) // overlap
DEFINE_CEPH_FEATURE(60, 1, BLKIN_TRACING)  // *do not share this bit*
DEFINE_CEPH_FEATURE(60, 1, OSD_RECOVERY_DELETES) // *do not share this bit*
DEFINE_CEPH_FEATURE(61, 1, CEPHX_V2)             // *do not share this bit*

DEFINE_CEPH_FEATURE(61, 1, RESERVED2)          // unused, but slow down!
DEFINE_CEPH_FEATURE(62, 1, RESERVED)           // do not use; used as a sentinal
DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facing

@@ -210,7 +210,8 @@ DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facin
	 CEPH_FEATURE_SERVER_JEWEL |		\
	 CEPH_FEATURE_MON_STATEFUL_SUB |	\
	 CEPH_FEATURE_CRUSH_TUNABLES5 |		\
	 CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING)
	 CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING |	\
	 CEPH_FEATURE_CEPHX_V2)

#define CEPH_FEATURES_REQUIRED_DEFAULT   \
	(CEPH_FEATURE_NOSRCADDR |	 \
+56 −17
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@

#include <linux/ceph/decode.h>
#include <linux/ceph/auth.h>
#include <linux/ceph/ceph_features.h>
#include <linux/ceph/libceph.h>
#include <linux/ceph/messenger.h>

@@ -803,6 +804,9 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
			  __le64 *psig)
{
	void *enc_buf = au->enc_buf;
	int ret;

	if (!CEPH_HAVE_FEATURE(msg->con->peer_features, CEPHX_V2)) {
		struct {
			__le32 len;
			__le32 header_crc;
@@ -810,19 +814,54 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
			__le32 middle_crc;
			__le32 data_crc;
		} __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
	int ret;

		sigblock->len = cpu_to_le32(4*sizeof(u32));
		sigblock->header_crc = msg->hdr.crc;
		sigblock->front_crc = msg->footer.front_crc;
		sigblock->middle_crc = msg->footer.middle_crc;
		sigblock->data_crc =  msg->footer.data_crc;
	ret = ceph_x_encrypt(&au->session_key, enc_buf, CEPHX_AU_ENC_BUF_LEN,
			     sizeof(*sigblock));

		ret = ceph_x_encrypt(&au->session_key, enc_buf,
				     CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock));
		if (ret < 0)
			return ret;

		*psig = *(__le64 *)(enc_buf + sizeof(u32));
	} else {
		struct {
			__le32 header_crc;
			__le32 front_crc;
			__le32 front_len;
			__le32 middle_crc;
			__le32 middle_len;
			__le32 data_crc;
			__le32 data_len;
			__le32 seq_lower_word;
		} __packed *sigblock = enc_buf;
		struct {
			__le64 a, b, c, d;
		} __packed *penc = enc_buf;
		int ciphertext_len;

		sigblock->header_crc = msg->hdr.crc;
		sigblock->front_crc = msg->footer.front_crc;
		sigblock->front_len = msg->hdr.front_len;
		sigblock->middle_crc = msg->footer.middle_crc;
		sigblock->middle_len = msg->hdr.middle_len;
		sigblock->data_crc =  msg->footer.data_crc;
		sigblock->data_len = msg->hdr.data_len;
		sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq;

		/* no leading len, no ceph_x_encrypt_header */
		ret = ceph_crypt(&au->session_key, true, enc_buf,
				 CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock),
				 &ciphertext_len);
		if (ret)
			return ret;

		*psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
	}

	return 0;
}