From e18d65ae9e7113831480f5c3efad015e83bc1200 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Fri, 1 Mar 2019 04:29:27 +0100 Subject: [PATCH] msg/async, v2: add flags field to frame's epilogue. Signed-off-by: Radoslaw Zarzynski --- src/msg/async/ProtocolV2.cc | 19 +++++++++++++------ src/msg/async/frames_v2.h | 38 ++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/msg/async/ProtocolV2.cc b/src/msg/async/ProtocolV2.cc index ebf0aa308cc8e..5cec45a4d9316 100644 --- a/src/msg/async/ProtocolV2.cc +++ b/src/msg/async/ProtocolV2.cc @@ -1391,16 +1391,16 @@ CtPtr ProtocolV2::handle_read_frame_epilogue_main(char *buffer, int r) << FRAME_EPILOGUE_SIZE << dendl; ceph_assert(session_stream_handlers.rx); - ceph_assert(FRAME_EPILOGUE_SIZE == \ + ceph_assert(sizeof(epilogue.integrity.auth_tag) == \ session_stream_handlers.rx->get_extra_size_at_final()); // I expect that ::temp_buffer is being used here. - ceph::bufferlist epilogue_bl; - epilogue_bl.push_back(buffer::create_static(FRAME_EPILOGUE_SIZE, - epilogue.auth_tag)); + ceph::bufferlist auth_tag_bl; + auth_tag_bl.push_back(buffer::create_static( + sizeof(epilogue.integrity.auth_tag), epilogue.integrity.auth_tag)); try { session_stream_handlers.rx->authenticated_decrypt_update_final( - std::move(epilogue_bl), segment_t::DEFAULT_ALIGNMENT); + std::move(auth_tag_bl), segment_t::DEFAULT_ALIGNMENT); } catch (ceph::crypto::onwire::MsgAuthError &e) { ldout(cct, 5) << __func__ << " message authentication failed: " << e.what() << dendl; @@ -1408,7 +1408,7 @@ CtPtr ProtocolV2::handle_read_frame_epilogue_main(char *buffer, int r) } } else { for (std::uint8_t idx = 0; idx < rx_segments_data.size(); idx++) { - const __u32 expected_crc = epilogue.crc_values[idx]; + const __u32 expected_crc = epilogue.integrity.crc[idx]; const __u32 calculated_crc = rx_segments_data[idx].crc32c(-1); if (expected_crc != calculated_crc) { ldout(cct, 5) << __func__ << " message integrity check failed: " @@ -1425,6 +1425,13 @@ CtPtr ProtocolV2::handle_read_frame_epilogue_main(char *buffer, int r) } } + // verify the late abort bit + if (epilogue.flags & FRAME_FLAGS_LATE_ABORT) { + ldout(cct, 5) << __func__ << " got LATE_ABORT request. Dropping frame" + << dendl; + return CONTINUE(read_frame); + } + return handle_read_frame_dispatch(); } diff --git a/src/msg/async/frames_v2.h b/src/msg/async/frames_v2.h index 85f333f5d55d3..d0f34b01d00e1 100644 --- a/src/msg/async/frames_v2.h +++ b/src/msg/async/frames_v2.h @@ -108,13 +108,23 @@ static_assert(std::is_standard_layout::value); // at the end of each frame holds: // * CRC32 for MAX_NUM_SEGMENTS -- in plain mode, // * cipher-specific data (e.g. auth tag for AES-GCM). -union epilogue_block_t { - char auth_tag[CRYPTO_BLOCK_SIZE]; - std::array<__le32, MAX_NUM_SEGMENTS> crc_values; -}; -static_assert(sizeof(epilogue_block_t) % CRYPTO_BLOCK_SIZE == 0); +// Additionally, it consists flags field used currently to abort message +// processing. It can be set by transceiver even very lately without any +// need for introducing buffering. +struct epilogue_block_t { + union { + char auth_tag[CRYPTO_BLOCK_SIZE]; + std::array<__le32, MAX_NUM_SEGMENTS> crc; + } integrity; + static_assert(sizeof(integrity.auth_tag) == CRYPTO_BLOCK_SIZE); + static_assert(sizeof(integrity.auth_tag) == sizeof(integrity.crc)); + + __u8 flags; +} __attribute__((packed)); static_assert(std::is_standard_layout::value); +static constexpr __u8 FRAME_FLAGS_LATE_ABORT = 0x1; + static constexpr uint32_t FRAME_PREAMBLE_SIZE = sizeof(preamble_block_t); static constexpr uint32_t FRAME_EPILOGUE_SIZE = sizeof(epilogue_block_t); @@ -171,7 +181,7 @@ public: ::memset(&epilogue, 0, sizeof(epilogue)); ceph::bufferlist::const_iterator hdriter(&this->payload, FRAME_PREAMBLE_SIZE); - epilogue.crc_values[SegmentIndex::Frame::PAYLOAD] = + epilogue.integrity.crc[SegmentIndex::Frame::PAYLOAD] = hdriter.crc32c(hdriter.get_remaining(), -1); this->payload.append(reinterpret_cast(&epilogue), sizeof(epilogue)); @@ -372,12 +382,14 @@ struct SignedEncryptedFrame : public PayloadFrame { session_stream_handlers.tx->authenticated_encrypt_update( std::move(c.payload)); c.payload = session_stream_handlers.tx->authenticated_encrypt_final(); + // append zeroized epilogue flags. CLEANME. + c.payload.append_zero(1); } else { epilogue_block_t epilogue; ::memset(&epilogue, 0, sizeof(epilogue)); ceph::bufferlist::const_iterator hdriter(&c.payload, FRAME_PREAMBLE_SIZE); - epilogue.crc_values[SegmentIndex::Frame::PAYLOAD] = + epilogue.integrity.crc[SegmentIndex::Frame::PAYLOAD] = hdriter.crc32c(hdriter.get_remaining(), -1); c.payload.append(reinterpret_cast(&epilogue), sizeof(epilogue)); } @@ -636,14 +648,18 @@ struct MessageHeaderFrame // auth tag will be appended at the end f.payload = session_stream_handlers.tx->authenticated_encrypt_final(); + // append zeroized epilogue flags. CLEANME. + f.payload.append_zero(1); } else { epilogue_block_t epilogue; + ::memset(&epilogue, 0, sizeof(epilogue)); + ceph::bufferlist::const_iterator hdriter(&f.payload, FRAME_PREAMBLE_SIZE); - epilogue.crc_values[SegmentIndex::Msg::HEADER] = + epilogue.integrity.crc[SegmentIndex::Msg::HEADER] = hdriter.crc32c(hdriter.get_remaining(), -1); - epilogue.crc_values[SegmentIndex::Msg::FRONT] = front.crc32c(-1), - epilogue.crc_values[SegmentIndex::Msg::MIDDLE] = middle.crc32c(-1), - epilogue.crc_values[SegmentIndex::Msg::DATA] = data.crc32c(-1), + epilogue.integrity.crc[SegmentIndex::Msg::FRONT] = front.crc32c(-1), + epilogue.integrity.crc[SegmentIndex::Msg::MIDDLE] = middle.crc32c(-1), + epilogue.integrity.crc[SegmentIndex::Msg::DATA] = data.crc32c(-1), f.payload.append(front); f.payload.append(middle); -- 2.39.5