4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

commit cc255c76c70f7a87d97939621eae04b600d9f4a1 upstream.

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: Ilya Dryomov <[email protected]>
Reviewed-by: Sage Weil <[email protected]>
Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
 include/linux/ceph/ceph_features.h |  7 +--
 net/ceph/auth_x.c                  | 73 +++++++++++++++++++++++-------
 2 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/include/linux/ceph/ceph_features.h 
b/include/linux/ceph/ceph_features.h
index 59042d5ac520..70f42eef813b 100644
--- a/include/linux/ceph/ceph_features.h
+++ b/include/linux/ceph/ceph_features.h
@@ -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
 
@@ -209,7 +209,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 |        \
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index ce28bb07d8fd..10eb759bbcb4 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -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,26 +804,64 @@ static int calc_signature(struct ceph_x_authorizer *au, 
struct ceph_msg *msg,
                          __le64 *psig)
 {
        void *enc_buf = au->enc_buf;
-       struct {
-               __le32 len;
-               __le32 header_crc;
-               __le32 front_crc;
-               __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));
-       if (ret < 0)
-               return ret;
+       if (!CEPH_HAVE_FEATURE(msg->con->peer_features, CEPHX_V2)) {
+               struct {
+                       __le32 len;
+                       __le32 header_crc;
+                       __le32 front_crc;
+                       __le32 middle_crc;
+                       __le32 data_crc;
+               } __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
+
+               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));
+               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;
+       }
 
-       *psig = *(__le64 *)(enc_buf + sizeof(u32));
        return 0;
 }
 
-- 
2.17.1



Reply via email to