diff options
9 files changed, 5 insertions, 689 deletions
diff --git a/recipes-extended/ceph/ceph/0001-mgr-require-all-caps-for-pre-octopus-tell-commands.patch b/recipes-extended/ceph/ceph/0001-mgr-require-all-caps-for-pre-octopus-tell-commands.patch deleted file mode 100644 index de191bf8..00000000 --- a/recipes-extended/ceph/ceph/0001-mgr-require-all-caps-for-pre-octopus-tell-commands.patch +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | From de67c1dab5597c91538970421b25f6ec667af492 Mon Sep 17 00:00:00 2001 | ||
2 | From: Josh Durgin <jdurgin@redhat.com> | ||
3 | Date: Mon, 4 May 2020 17:03:35 -0400 | ||
4 | Subject: [PATCH 1/3] mgr: require all caps for pre-octopus tell commands | ||
5 | |||
6 | This matches the requirements for admin socket commands | ||
7 | sent via tell elsewhere. | ||
8 | |||
9 | Signed-off-by: Josh Durgin <jdurgin@redhat.com> | ||
10 | |||
11 | Upstream-status: Backport | ||
12 | [https://github.com/ceph/ceph/commit/347003e13167c428187a5450517850f4d85e09ad] | ||
13 | |||
14 | Signed-off-by: Liu Haitao <haitao.liu@windriver.com> | ||
15 | --- | ||
16 | src/mgr/DaemonServer.cc | 37 ++++++++++++++++++++++--------------- | ||
17 | 1 file changed, 22 insertions(+), 15 deletions(-) | ||
18 | |||
19 | diff --git a/src/mgr/DaemonServer.cc b/src/mgr/DaemonServer.cc | ||
20 | index becd428a..527326e3 100644 | ||
21 | --- a/src/mgr/DaemonServer.cc | ||
22 | +++ b/src/mgr/DaemonServer.cc | ||
23 | @@ -808,20 +808,12 @@ public: | ||
24 | bool DaemonServer::handle_command(const ref_t<MCommand>& m) | ||
25 | { | ||
26 | std::lock_guard l(lock); | ||
27 | - // a blank fsid in MCommand signals a legacy client sending a "mon-mgr" CLI | ||
28 | - // command. | ||
29 | - if (m->fsid != uuid_d()) { | ||
30 | - cct->get_admin_socket()->queue_tell_command(m); | ||
31 | + auto cmdctx = std::make_shared<CommandContext>(m); | ||
32 | + try { | ||
33 | + return _handle_command(cmdctx); | ||
34 | + } catch (const bad_cmd_get& e) { | ||
35 | + cmdctx->reply(-EINVAL, e.what()); | ||
36 | return true; | ||
37 | - } else { | ||
38 | - // legacy client; send to CLI processing | ||
39 | - auto cmdctx = std::make_shared<CommandContext>(m); | ||
40 | - try { | ||
41 | - return _handle_command(cmdctx); | ||
42 | - } catch (const bad_cmd_get& e) { | ||
43 | - cmdctx->reply(-EINVAL, e.what()); | ||
44 | - return true; | ||
45 | - } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | @@ -853,8 +845,12 @@ bool DaemonServer::_handle_command( | ||
50 | std::shared_ptr<CommandContext>& cmdctx) | ||
51 | { | ||
52 | MessageRef m; | ||
53 | + bool admin_socket_cmd = false; | ||
54 | if (cmdctx->m_tell) { | ||
55 | m = cmdctx->m_tell; | ||
56 | + // a blank fsid in MCommand signals a legacy client sending a "mon-mgr" CLI | ||
57 | + // command. | ||
58 | + admin_socket_cmd = (cmdctx->m_tell->fsid != uuid_d()); | ||
59 | } else { | ||
60 | m = cmdctx->m_mgr; | ||
61 | } | ||
62 | @@ -888,7 +884,10 @@ bool DaemonServer::_handle_command( | ||
63 | |||
64 | dout(10) << "decoded-size=" << cmdctx->cmdmap.size() << " prefix=" << prefix << dendl; | ||
65 | |||
66 | - if (prefix == "get_command_descriptions") { | ||
67 | + // this is just for mgr commands - admin socket commands will fall | ||
68 | + // through and use the admin socket version of | ||
69 | + // get_command_descriptions | ||
70 | + if (prefix == "get_command_descriptions" && !admin_socket_cmd) { | ||
71 | dout(10) << "reading commands from python modules" << dendl; | ||
72 | const auto py_commands = py_modules.get_commands(); | ||
73 | |||
74 | @@ -925,7 +924,10 @@ bool DaemonServer::_handle_command( | ||
75 | |||
76 | bool is_allowed = false; | ||
77 | ModuleCommand py_command; | ||
78 | - if (!mgr_cmd) { | ||
79 | + if (admin_socket_cmd) { | ||
80 | + // admin socket commands require all capabilities | ||
81 | + is_allowed = session->caps.is_allow_all(); | ||
82 | + } else if (!mgr_cmd) { | ||
83 | // Resolve the command to the name of the module that will | ||
84 | // handle it (if the command exists) | ||
85 | auto py_commands = py_modules.get_py_commands(); | ||
86 | @@ -958,6 +960,11 @@ bool DaemonServer::_handle_command( | ||
87 | << "entity='" << session->entity_name << "' " | ||
88 | << "cmd=" << cmdctx->cmd << ": dispatch"; | ||
89 | |||
90 | + if (admin_socket_cmd) { | ||
91 | + cct->get_admin_socket()->queue_tell_command(cmdctx->m_tell); | ||
92 | + return true; | ||
93 | + } | ||
94 | + | ||
95 | // ---------------- | ||
96 | // service map commands | ||
97 | if (prefix == "service dump") { | ||
98 | -- | ||
99 | 2.25.1 | ||
100 | |||
diff --git a/recipes-extended/ceph/ceph/0001-msg-async-ProtocolV2-avoid-AES-GCM-nonce-reuse-vulne.patch b/recipes-extended/ceph/ceph/0001-msg-async-ProtocolV2-avoid-AES-GCM-nonce-reuse-vulne.patch deleted file mode 100644 index 54156698..00000000 --- a/recipes-extended/ceph/ceph/0001-msg-async-ProtocolV2-avoid-AES-GCM-nonce-reuse-vulne.patch +++ /dev/null | |||
@@ -1,256 +0,0 @@ | |||
1 | From 20b7bb685c5ea74c651ca1ea547ac66b0fee7035 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ilya Dryomov <idryomov@gmail.com> | ||
3 | Date: Fri, 6 Mar 2020 20:16:45 +0100 | ||
4 | Subject: [PATCH] msg/async/ProtocolV2: avoid AES-GCM nonce reuse | ||
5 | vulnerabilities | ||
6 | |||
7 | The secure mode uses AES-128-GCM with 96-bit nonces consisting of a | ||
8 | 32-bit counter followed by a 64-bit salt. The counter is incremented | ||
9 | after processing each frame, the salt is fixed for the duration of | ||
10 | the session. Both are initialized from the session key generated | ||
11 | during session negotiation, so the counter starts with essentially | ||
12 | a random value. It is allowed to wrap, and, after 2**32 frames, it | ||
13 | repeats, resulting in nonce reuse (the actual sequence numbers that | ||
14 | the messenger works with are 64-bit, so the session continues on). | ||
15 | |||
16 | Because of how GCM works, this completely breaks both confidentiality | ||
17 | and integrity aspects of the secure mode. A single nonce reuse reveals | ||
18 | the XOR of two plaintexts and almost completely reveals the subkey | ||
19 | used for producing authentication tags. After a few nonces get used | ||
20 | twice, all confidentiality and integrity goes out the window and the | ||
21 | attacker can potentially encrypt-authenticate plaintext of their | ||
22 | choice. | ||
23 | |||
24 | We can't easily change the nonce format to extend the counter to | ||
25 | 64 bits (and possibly XOR it with a longer salt). Instead, just | ||
26 | remember the initial nonce and cut the session before it repeats, | ||
27 | forcing renegotiation. | ||
28 | |||
29 | Signed-off-by: Ilya Dryomov <idryomov@gmail.com> | ||
30 | Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com> | ||
31 | Reviewed-by: Sage Weil <sage@redhat.com> | ||
32 | |||
33 | Conflicts: | ||
34 | src/msg/async/ProtocolV2.h [ context: commit ed3ec4c01d17 | ||
35 | ("msg: Build target 'common' without using namespace in | ||
36 | headers") not in octopus ] | ||
37 | |||
38 | CVE: CVE-2020-1759 | ||
39 | Upstream Status: Backport [20b7bb685c5ea74c651ca1ea547ac66b0fee7035] | ||
40 | |||
41 | Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> | ||
42 | --- | ||
43 | src/msg/async/ProtocolV2.cc | 62 ++++++++++++++++++++++++---------- | ||
44 | src/msg/async/ProtocolV2.h | 5 +-- | ||
45 | src/msg/async/crypto_onwire.cc | 17 ++++++++-- | ||
46 | src/msg/async/crypto_onwire.h | 5 +++ | ||
47 | 4 files changed, 67 insertions(+), 22 deletions(-) | ||
48 | |||
49 | diff --git a/src/msg/async/ProtocolV2.cc b/src/msg/async/ProtocolV2.cc | ||
50 | index 8fc02db6e5..c69f2ccf79 100644 | ||
51 | --- a/src/msg/async/ProtocolV2.cc | ||
52 | +++ b/src/msg/async/ProtocolV2.cc | ||
53 | @@ -533,7 +533,10 @@ ssize_t ProtocolV2::write_message(Message *m, bool more) { | ||
54 | m->get_payload(), | ||
55 | m->get_middle(), | ||
56 | m->get_data()); | ||
57 | - connection->outgoing_bl.append(message.get_buffer(session_stream_handlers)); | ||
58 | + if (!append_frame(message)) { | ||
59 | + m->put(); | ||
60 | + return -EILSEQ; | ||
61 | + } | ||
62 | |||
63 | ldout(cct, 5) << __func__ << " sending message m=" << m | ||
64 | << " seq=" << m->get_seq() << " " << *m << dendl; | ||
65 | @@ -566,15 +569,17 @@ ssize_t ProtocolV2::write_message(Message *m, bool more) { | ||
66 | return rc; | ||
67 | } | ||
68 | |||
69 | -void ProtocolV2::append_keepalive() { | ||
70 | - ldout(cct, 10) << __func__ << dendl; | ||
71 | - auto keepalive_frame = KeepAliveFrame::Encode(); | ||
72 | - connection->outgoing_bl.append(keepalive_frame.get_buffer(session_stream_handlers)); | ||
73 | -} | ||
74 | - | ||
75 | -void ProtocolV2::append_keepalive_ack(utime_t ×tamp) { | ||
76 | - auto keepalive_ack_frame = KeepAliveFrameAck::Encode(timestamp); | ||
77 | - connection->outgoing_bl.append(keepalive_ack_frame.get_buffer(session_stream_handlers)); | ||
78 | +template <class F> | ||
79 | +bool ProtocolV2::append_frame(F& frame) { | ||
80 | + ceph::bufferlist bl; | ||
81 | + try { | ||
82 | + bl = frame.get_buffer(session_stream_handlers); | ||
83 | + } catch (ceph::crypto::onwire::TxHandlerError &e) { | ||
84 | + ldout(cct, 1) << __func__ << " " << e.what() << dendl; | ||
85 | + return false; | ||
86 | + } | ||
87 | + connection->outgoing_bl.append(bl); | ||
88 | + return true; | ||
89 | } | ||
90 | |||
91 | void ProtocolV2::handle_message_ack(uint64_t seq) { | ||
92 | @@ -612,7 +617,15 @@ void ProtocolV2::write_event() { | ||
93 | connection->write_lock.lock(); | ||
94 | if (can_write) { | ||
95 | if (keepalive) { | ||
96 | - append_keepalive(); | ||
97 | + ldout(cct, 10) << __func__ << " appending keepalive" << dendl; | ||
98 | + auto keepalive_frame = KeepAliveFrame::Encode(); | ||
99 | + if (!append_frame(keepalive_frame)) { | ||
100 | + connection->write_lock.unlock(); | ||
101 | + connection->lock.lock(); | ||
102 | + fault(); | ||
103 | + connection->lock.unlock(); | ||
104 | + return; | ||
105 | + } | ||
106 | keepalive = false; | ||
107 | } | ||
108 | |||
109 | @@ -663,13 +676,16 @@ void ProtocolV2::write_event() { | ||
110 | if (r == 0) { | ||
111 | uint64_t left = ack_left; | ||
112 | if (left) { | ||
113 | - auto ack = AckFrame::Encode(in_seq); | ||
114 | - connection->outgoing_bl.append(ack.get_buffer(session_stream_handlers)); | ||
115 | ldout(cct, 10) << __func__ << " try send msg ack, acked " << left | ||
116 | << " messages" << dendl; | ||
117 | - ack_left -= left; | ||
118 | - left = ack_left; | ||
119 | - r = connection->_try_send(left); | ||
120 | + auto ack_frame = AckFrame::Encode(in_seq); | ||
121 | + if (append_frame(ack_frame)) { | ||
122 | + ack_left -= left; | ||
123 | + left = ack_left; | ||
124 | + r = connection->_try_send(left); | ||
125 | + } else { | ||
126 | + r = -EILSEQ; | ||
127 | + } | ||
128 | } else if (is_queued()) { | ||
129 | r = connection->_try_send(); | ||
130 | } | ||
131 | @@ -769,7 +785,13 @@ template <class F> | ||
132 | CtPtr ProtocolV2::write(const std::string &desc, | ||
133 | CONTINUATION_TYPE<ProtocolV2> &next, | ||
134 | F &frame) { | ||
135 | - ceph::bufferlist bl = frame.get_buffer(session_stream_handlers); | ||
136 | + ceph::bufferlist bl; | ||
137 | + try { | ||
138 | + bl = frame.get_buffer(session_stream_handlers); | ||
139 | + } catch (ceph::crypto::onwire::TxHandlerError &e) { | ||
140 | + ldout(cct, 1) << __func__ << " " << e.what() << dendl; | ||
141 | + return _fault(); | ||
142 | + } | ||
143 | return write(desc, next, bl); | ||
144 | } | ||
145 | |||
146 | @@ -1672,7 +1694,11 @@ CtPtr ProtocolV2::handle_keepalive2(ceph::bufferlist &payload) | ||
147 | ldout(cct, 30) << __func__ << " got KEEPALIVE2 tag ..." << dendl; | ||
148 | |||
149 | connection->write_lock.lock(); | ||
150 | - append_keepalive_ack(keepalive_frame.timestamp()); | ||
151 | + auto keepalive_ack_frame = KeepAliveFrameAck::Encode(keepalive_frame.timestamp()); | ||
152 | + if (!append_frame(keepalive_ack_frame)) { | ||
153 | + connection->write_lock.unlock(); | ||
154 | + return _fault(); | ||
155 | + } | ||
156 | connection->write_lock.unlock(); | ||
157 | |||
158 | ldout(cct, 20) << __func__ << " got KEEPALIVE2 " | ||
159 | diff --git a/src/msg/async/ProtocolV2.h b/src/msg/async/ProtocolV2.h | ||
160 | index 2dbe647ae5..9897d18cf2 100644 | ||
161 | --- a/src/msg/async/ProtocolV2.h | ||
162 | +++ b/src/msg/async/ProtocolV2.h | ||
163 | @@ -129,6 +129,9 @@ private: | ||
164 | CONTINUATION_TYPE<ProtocolV2> &next, | ||
165 | bufferlist &buffer); | ||
166 | |||
167 | + template <class F> | ||
168 | + bool append_frame(F& frame); | ||
169 | + | ||
170 | void requeue_sent(); | ||
171 | uint64_t discard_requeued_up_to(uint64_t out_seq, uint64_t seq); | ||
172 | void reset_recv_state(); | ||
173 | @@ -140,8 +143,6 @@ private: | ||
174 | void prepare_send_message(uint64_t features, Message *m); | ||
175 | out_queue_entry_t _get_next_outgoing(); | ||
176 | ssize_t write_message(Message *m, bool more); | ||
177 | - void append_keepalive(); | ||
178 | - void append_keepalive_ack(utime_t ×tamp); | ||
179 | void handle_message_ack(uint64_t seq); | ||
180 | |||
181 | CONTINUATION_DECL(ProtocolV2, _wait_for_peer_banner); | ||
182 | diff --git a/src/msg/async/crypto_onwire.cc b/src/msg/async/crypto_onwire.cc | ||
183 | index acf3f66689..07e7fe6553 100644 | ||
184 | --- a/src/msg/async/crypto_onwire.cc | ||
185 | +++ b/src/msg/async/crypto_onwire.cc | ||
186 | @@ -22,6 +22,10 @@ static constexpr const std::size_t AESGCM_BLOCK_LEN{16}; | ||
187 | struct nonce_t { | ||
188 | std::uint32_t random_seq; | ||
189 | std::uint64_t random_rest; | ||
190 | + | ||
191 | + bool operator==(const nonce_t& rhs) const { | ||
192 | + return !memcmp(this, &rhs, sizeof(*this)); | ||
193 | + } | ||
194 | } __attribute__((packed)); | ||
195 | static_assert(sizeof(nonce_t) == AESGCM_IV_LEN); | ||
196 | |||
197 | @@ -35,7 +39,8 @@ class AES128GCM_OnWireTxHandler : public ceph::crypto::onwire::TxHandler { | ||
198 | CephContext* const cct; | ||
199 | std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ectx; | ||
200 | ceph::bufferlist buffer; | ||
201 | - nonce_t nonce; | ||
202 | + nonce_t nonce, initial_nonce; | ||
203 | + bool used_initial_nonce; | ||
204 | static_assert(sizeof(nonce) == AESGCM_IV_LEN); | ||
205 | |||
206 | public: | ||
207 | @@ -44,7 +49,7 @@ public: | ||
208 | const nonce_t& nonce) | ||
209 | : cct(cct), | ||
210 | ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free), | ||
211 | - nonce(nonce) { | ||
212 | + nonce(nonce), initial_nonce(nonce), used_initial_nonce(false) { | ||
213 | ceph_assert_always(ectx); | ||
214 | ceph_assert_always(key.size() * CHAR_BIT == 128); | ||
215 | |||
216 | @@ -61,6 +66,7 @@ public: | ||
217 | |||
218 | ~AES128GCM_OnWireTxHandler() override { | ||
219 | ::ceph::crypto::zeroize_for_security(&nonce, sizeof(nonce)); | ||
220 | + ::ceph::crypto::zeroize_for_security(&initial_nonce, sizeof(initial_nonce)); | ||
221 | } | ||
222 | |||
223 | std::uint32_t calculate_segment_size(std::uint32_t size) override | ||
224 | @@ -78,6 +84,13 @@ public: | ||
225 | void AES128GCM_OnWireTxHandler::reset_tx_handler( | ||
226 | std::initializer_list<std::uint32_t> update_size_sequence) | ||
227 | { | ||
228 | + if (nonce == initial_nonce) { | ||
229 | + if (used_initial_nonce) { | ||
230 | + throw ceph::crypto::onwire::TxHandlerError("out of nonces"); | ||
231 | + } | ||
232 | + used_initial_nonce = true; | ||
233 | + } | ||
234 | + | ||
235 | if(1 != EVP_EncryptInit_ex(ectx.get(), nullptr, nullptr, nullptr, | ||
236 | reinterpret_cast<const unsigned char*>(&nonce))) { | ||
237 | throw std::runtime_error("EVP_EncryptInit_ex failed"); | ||
238 | diff --git a/src/msg/async/crypto_onwire.h b/src/msg/async/crypto_onwire.h | ||
239 | index bd682e8c71..0c544f205a 100644 | ||
240 | --- a/src/msg/async/crypto_onwire.h | ||
241 | +++ b/src/msg/async/crypto_onwire.h | ||
242 | @@ -45,6 +45,11 @@ struct MsgAuthError : public std::runtime_error { | ||
243 | } | ||
244 | }; | ||
245 | |||
246 | +struct TxHandlerError : public std::runtime_error { | ||
247 | + TxHandlerError(const char* what) | ||
248 | + : std::runtime_error(std::string("tx handler error: ") + what) {} | ||
249 | +}; | ||
250 | + | ||
251 | struct TxHandler { | ||
252 | virtual ~TxHandler() = default; | ||
253 | |||
254 | -- | ||
255 | 2.20.1 | ||
256 | |||
diff --git a/recipes-extended/ceph/ceph/0001-msg-async-crypto_onwire-fix-endianness-of-nonce_t.patch b/recipes-extended/ceph/ceph/0001-msg-async-crypto_onwire-fix-endianness-of-nonce_t.patch deleted file mode 100644 index ad8a2055..00000000 --- a/recipes-extended/ceph/ceph/0001-msg-async-crypto_onwire-fix-endianness-of-nonce_t.patch +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | From dfd1d81cec62e21e21696dc87d4db5f920e51a67 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ilya Dryomov <idryomov@gmail.com> | ||
3 | Date: Fri, 6 Mar 2020 20:16:45 +0100 | ||
4 | Subject: [PATCH] msg/async/crypto_onwire: fix endianness of nonce_t | ||
5 | |||
6 | As a AES-GCM IV, nonce_t is implicitly shared between server and | ||
7 | client. Currently, if their endianness doesn't match, they are unable | ||
8 | to communicate in secure mode because each gets its own idea of what | ||
9 | the next nonce should be after the counter is incremented. | ||
10 | |||
11 | Several RFCs state that the nonce counter should be BE, but since we | ||
12 | use LE for everything on-disk and on-wire, make it LE. | ||
13 | |||
14 | Signed-off-by: Ilya Dryomov <idryomov@gmail.com> | ||
15 | Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com> | ||
16 | Reviewed-by: Sage Weil <sage@redhat.com> | ||
17 | |||
18 | CVE: CVE-2020-1759 | ||
19 | Upstream Status: Backport [dfd1d81cec62e21e21696dc87d4db5f920e51a67] | ||
20 | |||
21 | Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> | ||
22 | --- | ||
23 | src/msg/async/crypto_onwire.cc | 8 ++++---- | ||
24 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
25 | |||
26 | diff --git a/src/msg/async/crypto_onwire.cc b/src/msg/async/crypto_onwire.cc | ||
27 | index 07e7fe6553..c39632cbd6 100644 | ||
28 | --- a/src/msg/async/crypto_onwire.cc | ||
29 | +++ b/src/msg/async/crypto_onwire.cc | ||
30 | @@ -20,8 +20,8 @@ static constexpr const std::size_t AESGCM_TAG_LEN{16}; | ||
31 | static constexpr const std::size_t AESGCM_BLOCK_LEN{16}; | ||
32 | |||
33 | struct nonce_t { | ||
34 | - std::uint32_t random_seq; | ||
35 | - std::uint64_t random_rest; | ||
36 | + ceph_le32 random_seq; | ||
37 | + ceph_le64 random_rest; | ||
38 | |||
39 | bool operator==(const nonce_t& rhs) const { | ||
40 | return !memcmp(this, &rhs, sizeof(*this)); | ||
41 | @@ -99,7 +99,7 @@ void AES128GCM_OnWireTxHandler::reset_tx_handler( | ||
42 | buffer.reserve(std::accumulate(std::begin(update_size_sequence), | ||
43 | std::end(update_size_sequence), AESGCM_TAG_LEN)); | ||
44 | |||
45 | - ++nonce.random_seq; | ||
46 | + nonce.random_seq = nonce.random_seq + 1; | ||
47 | } | ||
48 | |||
49 | void AES128GCM_OnWireTxHandler::authenticated_encrypt_update( | ||
50 | @@ -204,7 +204,7 @@ void AES128GCM_OnWireRxHandler::reset_rx_handler() | ||
51 | reinterpret_cast<const unsigned char*>(&nonce))) { | ||
52 | throw std::runtime_error("EVP_DecryptInit_ex failed"); | ||
53 | } | ||
54 | - ++nonce.random_seq; | ||
55 | + nonce.random_seq = nonce.random_seq + 1; | ||
56 | } | ||
57 | |||
58 | ceph::bufferlist AES128GCM_OnWireRxHandler::authenticated_decrypt_update( | ||
59 | -- | ||
60 | 2.20.1 | ||
61 | |||
diff --git a/recipes-extended/ceph/ceph/0001-rgw-EPERM-to-ERR_INVALID_REQUEST.patch b/recipes-extended/ceph/ceph/0001-rgw-EPERM-to-ERR_INVALID_REQUEST.patch deleted file mode 100644 index 30906d7c..00000000 --- a/recipes-extended/ceph/ceph/0001-rgw-EPERM-to-ERR_INVALID_REQUEST.patch +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | From 92da834cababc4dddd5dbbab5837310478d1e6d4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Abhishek Lekshmanan <abhishek@suse.com> | ||
3 | Date: Fri, 27 Mar 2020 19:29:01 +0100 | ||
4 | Subject: [PATCH] rgw: EPERM to ERR_INVALID_REQUEST | ||
5 | |||
6 | As per Robin's comments and S3 spec | ||
7 | |||
8 | Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com> | ||
9 | |||
10 | CVE: CVE-2020-1760 | ||
11 | Upstream Status: Backport [92da834cababc4dddd5dbbab5837310478d1e6d4] | ||
12 | |||
13 | Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> | ||
14 | --- | ||
15 | src/rgw/rgw_rest_s3.cc | 2 +- | ||
16 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
17 | |||
18 | diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc | ||
19 | index 1bfc8312de..f13ae23dd6 100644 | ||
20 | --- a/src/rgw/rgw_rest_s3.cc | ||
21 | +++ b/src/rgw/rgw_rest_s3.cc | ||
22 | @@ -301,7 +301,7 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs, | ||
23 | /* reject unauthenticated response header manipulation, see | ||
24 | * https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html */ | ||
25 | if (s->auth.identity->is_anonymous()) { | ||
26 | - return -EPERM; | ||
27 | + return -ERR_INVALID_REQUEST; | ||
28 | } | ||
29 | if (strcmp(p->param, "response-content-type") != 0) { | ||
30 | response_attrs[p->http_attr] = val; | ||
31 | -- | ||
32 | 2.20.1 | ||
33 | |||
diff --git a/recipes-extended/ceph/ceph/0001-rgw-reject-control-characters-in-response-header-act.patch b/recipes-extended/ceph/ceph/0001-rgw-reject-control-characters-in-response-header-act.patch deleted file mode 100644 index af0fc79a..00000000 --- a/recipes-extended/ceph/ceph/0001-rgw-reject-control-characters-in-response-header-act.patch +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | From be7679007c3dfab3e19c22c38c36ccac91828e3b Mon Sep 17 00:00:00 2001 | ||
2 | From: "Robin H. Johnson" <rjohnson@digitalocean.com> | ||
3 | Date: Fri, 27 Mar 2020 20:48:13 +0100 | ||
4 | Subject: [PATCH] rgw: reject control characters in response-header actions | ||
5 | |||
6 | S3 GetObject permits overriding response header values, but those inputs | ||
7 | need to be validated to insure only characters that are valid in an HTTP | ||
8 | header value are present. | ||
9 | |||
10 | Credit: Initial vulnerability discovery by William Bowling (@wcbowling) | ||
11 | Credit: Further vulnerability discovery by Robin H. Johnson <rjohnson@digitalocean.com> | ||
12 | Signed-off-by: Robin H. Johnson <rjohnson@digitalocean.com> | ||
13 | |||
14 | CVE: CVE-2020-1760 | ||
15 | Upstream Status: Backport [be7679007c3dfab3e19c22c38c36ccac91828e3b] | ||
16 | |||
17 | Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> | ||
18 | --- | ||
19 | src/rgw/rgw_rest_s3.cc | 22 ++++++++++++++++++++++ | ||
20 | 1 file changed, 22 insertions(+) | ||
21 | |||
22 | diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc | ||
23 | index f13ae23dd6..0de040968c 100644 | ||
24 | --- a/src/rgw/rgw_rest_s3.cc | ||
25 | +++ b/src/rgw/rgw_rest_s3.cc | ||
26 | @@ -189,6 +189,15 @@ int decode_attr_bl_single_value(map<string, bufferlist>& attrs, const char *attr | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | +inline bool str_has_cntrl(const std::string s) { | ||
31 | + return std::any_of(s.begin(), s.end(), ::iscntrl); | ||
32 | +} | ||
33 | + | ||
34 | +inline bool str_has_cntrl(const char* s) { | ||
35 | + std::string _s(s); | ||
36 | + return str_has_cntrl(_s); | ||
37 | +} | ||
38 | + | ||
39 | int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs, | ||
40 | off_t bl_len) | ||
41 | { | ||
42 | @@ -303,6 +312,19 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs, | ||
43 | if (s->auth.identity->is_anonymous()) { | ||
44 | return -ERR_INVALID_REQUEST; | ||
45 | } | ||
46 | + /* HTTP specification says no control characters should be present in | ||
47 | + * header values: https://tools.ietf.org/html/rfc7230#section-3.2 | ||
48 | + * field-vchar = VCHAR / obs-text | ||
49 | + * | ||
50 | + * Failure to validate this permits a CRLF injection in HTTP headers, | ||
51 | + * whereas S3 GetObject only permits specific headers. | ||
52 | + */ | ||
53 | + if(str_has_cntrl(val)) { | ||
54 | + /* TODO: return a more distinct error in future; | ||
55 | + * stating what the problem is */ | ||
56 | + return -ERR_INVALID_REQUEST; | ||
57 | + } | ||
58 | + | ||
59 | if (strcmp(p->param, "response-content-type") != 0) { | ||
60 | response_attrs[p->http_attr] = val; | ||
61 | } else { | ||
62 | -- | ||
63 | 2.20.1 | ||
64 | |||
diff --git a/recipes-extended/ceph/ceph/0001-rgw-reject-unauthenticated-response-header-actions.patch b/recipes-extended/ceph/ceph/0001-rgw-reject-unauthenticated-response-header-actions.patch deleted file mode 100644 index ae241473..00000000 --- a/recipes-extended/ceph/ceph/0001-rgw-reject-unauthenticated-response-header-actions.patch +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | From 8f90658c731499722d5f4393c8ad70b971d05f77 Mon Sep 17 00:00:00 2001 | ||
2 | From: Matt Benjamin <mbenjamin@redhat.com> | ||
3 | Date: Fri, 27 Mar 2020 18:13:48 +0100 | ||
4 | Subject: [PATCH] rgw: reject unauthenticated response-header actions | ||
5 | |||
6 | Signed-off-by: Matt Benjamin <mbenjamin@redhat.com> | ||
7 | Reviewed-by: Casey Bodley <cbodley@redhat.com> | ||
8 | (cherry picked from commit d8dd5e513c0c62bbd7d3044d7e2eddcd897bd400) | ||
9 | |||
10 | CVE: CVE-2020-1760 | ||
11 | Upstream Status: Backport [8f90658c731499722d5f4393c8ad70b971d05f77] | ||
12 | |||
13 | Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> | ||
14 | --- | ||
15 | src/rgw/rgw_rest_s3.cc | 5 +++++ | ||
16 | 1 file changed, 5 insertions(+) | ||
17 | |||
18 | diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc | ||
19 | index 532d738b58..1bfc8312de 100644 | ||
20 | --- a/src/rgw/rgw_rest_s3.cc | ||
21 | +++ b/src/rgw/rgw_rest_s3.cc | ||
22 | @@ -298,6 +298,11 @@ int RGWGetObj_ObjStore_S3::send_response_data(bufferlist& bl, off_t bl_ofs, | ||
23 | bool exists; | ||
24 | string val = s->info.args.get(p->param, &exists); | ||
25 | if (exists) { | ||
26 | + /* reject unauthenticated response header manipulation, see | ||
27 | + * https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html */ | ||
28 | + if (s->auth.identity->is_anonymous()) { | ||
29 | + return -EPERM; | ||
30 | + } | ||
31 | if (strcmp(p->param, "response-content-type") != 0) { | ||
32 | response_attrs[p->http_attr] = val; | ||
33 | } else { | ||
34 | -- | ||
35 | 2.20.1 | ||
36 | |||
diff --git a/recipes-extended/ceph/ceph/0002-mon-enforce-caps-for-pre-octopus-client-tell-command.patch b/recipes-extended/ceph/ceph/0002-mon-enforce-caps-for-pre-octopus-client-tell-command.patch deleted file mode 100644 index 79f2174b..00000000 --- a/recipes-extended/ceph/ceph/0002-mon-enforce-caps-for-pre-octopus-client-tell-command.patch +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | From ddbac9b2779172876ebd2d26b68b04b02350a125 Mon Sep 17 00:00:00 2001 | ||
2 | From: Josh Durgin <jdurgin@redhat.com> | ||
3 | Date: Thu, 23 Apr 2020 00:22:10 -0400 | ||
4 | Subject: [PATCH 2/3] mon: enforce caps for pre-octopus client tell commands | ||
5 | |||
6 | This affects only the commands whitelisted here - in particular | ||
7 | injectargs requires write access to the monitors. | ||
8 | |||
9 | Signed-off-by: Josh Durgin <jdurgin@redhat.com> | ||
10 | |||
11 | Upstream-status: Backport | ||
12 | [https://github.com/ceph/ceph/commit/fc5e56b75a97c4652c87e9959aad1c4dec45010d] | ||
13 | |||
14 | Signed-off-by: Liu Haitao <haitao.liu@windriver.com> | ||
15 | --- | ||
16 | src/mon/Monitor.cc | 56 +++++++++++++++++++++++----------------------- | ||
17 | 1 file changed, 28 insertions(+), 28 deletions(-) | ||
18 | |||
19 | diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc | ||
20 | index b7cb3eae..eecd2f68 100644 | ||
21 | --- a/src/mon/Monitor.cc | ||
22 | +++ b/src/mon/Monitor.cc | ||
23 | @@ -3226,34 +3226,6 @@ void Monitor::handle_command(MonOpRequestRef op) | ||
24 | return; | ||
25 | } | ||
26 | |||
27 | - // compat kludge for legacy clients trying to tell commands that are | ||
28 | - // new. see bottom of MonCommands.h. we need to handle both (1) | ||
29 | - // pre-octopus clients and (2) octopus clients with a mix of pre-octopus | ||
30 | - // and octopus mons. | ||
31 | - if ((!HAVE_FEATURE(m->get_connection()->get_features(), SERVER_OCTOPUS) || | ||
32 | - monmap->min_mon_release < ceph_release_t::octopus) && | ||
33 | - (prefix == "injectargs" || | ||
34 | - prefix == "smart" || | ||
35 | - prefix == "mon_status" || | ||
36 | - prefix == "heap")) { | ||
37 | - if (m->get_connection()->get_messenger() == 0) { | ||
38 | - // Prior to octopus, monitors might forward these messages | ||
39 | - // around. that was broken at baseline, and if we try to process | ||
40 | - // this message now, it will assert out when we try to send a | ||
41 | - // message in reply from the asok/tell worker (see | ||
42 | - // AnonConnection). Just reply with an error. | ||
43 | - dout(5) << __func__ << " failing forwarded command from a (presumably) " | ||
44 | - << "pre-octopus peer" << dendl; | ||
45 | - reply_command( | ||
46 | - op, -EBUSY, | ||
47 | - "failing forwarded tell command in mixed-version mon cluster", 0); | ||
48 | - return; | ||
49 | - } | ||
50 | - dout(5) << __func__ << " passing command to tell/asok" << dendl; | ||
51 | - cct->get_admin_socket()->queue_tell_command(m); | ||
52 | - return; | ||
53 | - } | ||
54 | - | ||
55 | string module; | ||
56 | string err; | ||
57 | |||
58 | @@ -3368,6 +3340,34 @@ void Monitor::handle_command(MonOpRequestRef op) | ||
59 | << "entity='" << session->entity_name << "' " | ||
60 | << "cmd=" << m->cmd << ": dispatch"; | ||
61 | |||
62 | + // compat kludge for legacy clients trying to tell commands that are | ||
63 | + // new. see bottom of MonCommands.h. we need to handle both (1) | ||
64 | + // pre-octopus clients and (2) octopus clients with a mix of pre-octopus | ||
65 | + // and octopus mons. | ||
66 | + if ((!HAVE_FEATURE(m->get_connection()->get_features(), SERVER_OCTOPUS) || | ||
67 | + monmap->min_mon_release < ceph_release_t::octopus) && | ||
68 | + (prefix == "injectargs" || | ||
69 | + prefix == "smart" || | ||
70 | + prefix == "mon_status" || | ||
71 | + prefix == "heap")) { | ||
72 | + if (m->get_connection()->get_messenger() == 0) { | ||
73 | + // Prior to octopus, monitors might forward these messages | ||
74 | + // around. that was broken at baseline, and if we try to process | ||
75 | + // this message now, it will assert out when we try to send a | ||
76 | + // message in reply from the asok/tell worker (see | ||
77 | + // AnonConnection). Just reply with an error. | ||
78 | + dout(5) << __func__ << " failing forwarded command from a (presumably) " | ||
79 | + << "pre-octopus peer" << dendl; | ||
80 | + reply_command( | ||
81 | + op, -EBUSY, | ||
82 | + "failing forwarded tell command in mixed-version mon cluster", 0); | ||
83 | + return; | ||
84 | + } | ||
85 | + dout(5) << __func__ << " passing command to tell/asok" << dendl; | ||
86 | + cct->get_admin_socket()->queue_tell_command(m); | ||
87 | + return; | ||
88 | + } | ||
89 | + | ||
90 | if (mon_cmd->is_mgr()) { | ||
91 | const auto& hdr = m->get_header(); | ||
92 | uint64_t size = hdr.front_len + hdr.middle_len + hdr.data_len; | ||
93 | -- | ||
94 | 2.25.1 | ||
95 | |||
diff --git a/recipes-extended/ceph/ceph/0003-PendingReleaseNotes-note-about-security-fix.patch b/recipes-extended/ceph/ceph/0003-PendingReleaseNotes-note-about-security-fix.patch deleted file mode 100644 index ed2a63e7..00000000 --- a/recipes-extended/ceph/ceph/0003-PendingReleaseNotes-note-about-security-fix.patch +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | From 56800925651857821034ac9c8ec82d45635cc3b8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Josh Durgin <jdurgin@redhat.com> | ||
3 | Date: Wed, 13 May 2020 21:34:56 -0700 | ||
4 | Subject: [PATCH 3/3] PendingReleaseNotes: note about security fix | ||
5 | |||
6 | Signed-off-by: Josh Durgin <jdurgin@redhat.com> | ||
7 | |||
8 | Upstream-status: Backport | ||
9 | [https://github.com/ceph/ceph/commit/06f239fc35f35865d2cf92dda1ac8f4d5fe82bde] | ||
10 | |||
11 | Signed-off-by: Liu Haitao <haitao.liu@windriver.com> | ||
12 | --- | ||
13 | PendingReleaseNotes | 2 ++ | ||
14 | 1 file changed, 2 insertions(+) | ||
15 | |||
16 | diff --git a/PendingReleaseNotes b/PendingReleaseNotes | ||
17 | index c9fd4c79..6e07ce6d 100644 | ||
18 | --- a/PendingReleaseNotes | ||
19 | +++ b/PendingReleaseNotes | ||
20 | @@ -1,6 +1,8 @@ | ||
21 | >=15.0.0 | ||
22 | -------- | ||
23 | |||
24 | +* CVE-2020-10736: Fixes an authorization bypass in monitor and manager daemons | ||
25 | + | ||
26 | * The RGW "num_rados_handles" has been removed. | ||
27 | * If you were using a value of "num_rados_handles" greater than 1 | ||
28 | multiply your current "objecter_inflight_ops" and | ||
29 | -- | ||
30 | 2.25.1 | ||
31 | |||
diff --git a/recipes-extended/ceph/ceph_15.2.0.bb b/recipes-extended/ceph/ceph_15.2.8.bb index 8454a200..f771baa2 100644 --- a/recipes-extended/ceph/ceph_15.2.0.bb +++ b/recipes-extended/ceph/ceph_15.2.8.bb | |||
@@ -12,23 +12,15 @@ SRC_URI = "http://download.ceph.com/tarballs/ceph-${PV}.tar.gz \ | |||
12 | file://0001-ceph-fix-build-errors-for-cross-compile.patch \ | 12 | file://0001-ceph-fix-build-errors-for-cross-compile.patch \ |
13 | file://0001-fix-host-library-paths-were-used.patch \ | 13 | file://0001-fix-host-library-paths-were-used.patch \ |
14 | file://ceph.conf \ | 14 | file://ceph.conf \ |
15 | file://0001-msg-async-ProtocolV2-avoid-AES-GCM-nonce-reuse-vulne.patch \ | ||
16 | file://0001-msg-async-crypto_onwire-fix-endianness-of-nonce_t.patch \ | ||
17 | file://0001-rgw-reject-unauthenticated-response-header-actions.patch \ | ||
18 | file://0001-rgw-EPERM-to-ERR_INVALID_REQUEST.patch \ | ||
19 | file://0001-rgw-reject-control-characters-in-response-header-act.patch \ | ||
20 | file://0001-mgr-require-all-caps-for-pre-octopus-tell-commands.patch \ | ||
21 | file://0002-mon-enforce-caps-for-pre-octopus-client-tell-command.patch \ | ||
22 | file://0003-PendingReleaseNotes-note-about-security-fix.patch \ | ||
23 | file://0001-add-missing-include-for-atomic-bool.patch \ | 15 | file://0001-add-missing-include-for-atomic-bool.patch \ |
24 | file://0001-cmake-add-support-for-python3.9.patch \ | 16 | file://0001-cmake-add-support-for-python3.9.patch \ |
25 | " | 17 | " |
26 | 18 | ||
27 | SRC_URI[md5sum] = "1f9af648b4c6d19975aab2583ab99710" | 19 | SRC_URI[md5sum] = "cab93dadfe38888561d390fd58b8c947" |
28 | SRC_URI[sha256sum] = "4292c473d1714a6602c525d7582e4e03ec608f0a1cbc0dd338207e5c7068e0d3" | 20 | SRC_URI[sha256sum] = "64c5eaf8c1e4092e59bc538e9241b6d5cf4ffca92563031abbea8b37b4cab9da" |
29 | SRC_URI[sha1sum] = "7158806ece1483fcccdf1172c20cc34d9401c543" | 21 | SRC_URI[sha1sum] = "77b60c3775cd6e38f2d07870aee550368105c74b" |
30 | SRC_URI[sha384sum] = "20e996dbf30d1e33a6d6aae36960190125ce263d306415bcec5d2b3032b8b8f730deeba3ca318576573127d08909404a" | 22 | SRC_URI[sha384sum] = "2173c5176e9ff3745e4bc493585a8cf14e9e7737cf575551a010b7b84cd6b88b378dc93e6509b3a696732c51f530fa60" |
31 | SRC_URI[sha512sum] = "07a3ff2ccf1a3abac652ff8c5f1611e7c628fcedcb280adc6cd49792b46fa50c7c29437dc57c2c4a6af708a6833abf8c1a386ef2142d30bd5e1f214ba7aec4f2" | 23 | SRC_URI[sha512sum] = "66c7322575165b4747955ac9de34f9f9e2d4361c8cd8498819383883045601b92f786c4336c79369d6f019db1c4524c492faa40cdceed7fc1b2b373ca6ab5065" |
32 | 24 | ||
33 | DEPENDS = "boost bzip2 curl expat gperf-native \ | 25 | DEPENDS = "boost bzip2 curl expat gperf-native \ |
34 | keyutils libaio libibverbs lz4 \ | 26 | keyutils libaio libibverbs lz4 \ |