summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recipes-extended/ceph/ceph/0001-mgr-require-all-caps-for-pre-octopus-tell-commands.patch100
-rw-r--r--recipes-extended/ceph/ceph/0001-msg-async-ProtocolV2-avoid-AES-GCM-nonce-reuse-vulne.patch256
-rw-r--r--recipes-extended/ceph/ceph/0001-msg-async-crypto_onwire-fix-endianness-of-nonce_t.patch61
-rw-r--r--recipes-extended/ceph/ceph/0001-rgw-EPERM-to-ERR_INVALID_REQUEST.patch33
-rw-r--r--recipes-extended/ceph/ceph/0001-rgw-reject-control-characters-in-response-header-act.patch64
-rw-r--r--recipes-extended/ceph/ceph/0001-rgw-reject-unauthenticated-response-header-actions.patch36
-rw-r--r--recipes-extended/ceph/ceph/0002-mon-enforce-caps-for-pre-octopus-client-tell-command.patch95
-rw-r--r--recipes-extended/ceph/ceph/0003-PendingReleaseNotes-note-about-security-fix.patch31
-rw-r--r--recipes-extended/ceph/ceph_15.2.8.bb (renamed from recipes-extended/ceph/ceph_15.2.0.bb)18
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 @@
1From de67c1dab5597c91538970421b25f6ec667af492 Mon Sep 17 00:00:00 2001
2From: Josh Durgin <jdurgin@redhat.com>
3Date: Mon, 4 May 2020 17:03:35 -0400
4Subject: [PATCH 1/3] mgr: require all caps for pre-octopus tell commands
5
6This matches the requirements for admin socket commands
7sent via tell elsewhere.
8
9Signed-off-by: Josh Durgin <jdurgin@redhat.com>
10
11Upstream-status: Backport
12[https://github.com/ceph/ceph/commit/347003e13167c428187a5450517850f4d85e09ad]
13
14Signed-off-by: Liu Haitao <haitao.liu@windriver.com>
15---
16 src/mgr/DaemonServer.cc | 37 ++++++++++++++++++++++---------------
17 1 file changed, 22 insertions(+), 15 deletions(-)
18
19diff --git a/src/mgr/DaemonServer.cc b/src/mgr/DaemonServer.cc
20index 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--
992.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 @@
1From 20b7bb685c5ea74c651ca1ea547ac66b0fee7035 Mon Sep 17 00:00:00 2001
2From: Ilya Dryomov <idryomov@gmail.com>
3Date: Fri, 6 Mar 2020 20:16:45 +0100
4Subject: [PATCH] msg/async/ProtocolV2: avoid AES-GCM nonce reuse
5 vulnerabilities
6
7The secure mode uses AES-128-GCM with 96-bit nonces consisting of a
832-bit counter followed by a 64-bit salt. The counter is incremented
9after processing each frame, the salt is fixed for the duration of
10the session. Both are initialized from the session key generated
11during session negotiation, so the counter starts with essentially
12a random value. It is allowed to wrap, and, after 2**32 frames, it
13repeats, resulting in nonce reuse (the actual sequence numbers that
14the messenger works with are 64-bit, so the session continues on).
15
16Because of how GCM works, this completely breaks both confidentiality
17and integrity aspects of the secure mode. A single nonce reuse reveals
18the XOR of two plaintexts and almost completely reveals the subkey
19used for producing authentication tags. After a few nonces get used
20twice, all confidentiality and integrity goes out the window and the
21attacker can potentially encrypt-authenticate plaintext of their
22choice.
23
24We can't easily change the nonce format to extend the counter to
2564 bits (and possibly XOR it with a longer salt). Instead, just
26remember the initial nonce and cut the session before it repeats,
27forcing renegotiation.
28
29Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
30Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
31Reviewed-by: Sage Weil <sage@redhat.com>
32
33Conflicts:
34 src/msg/async/ProtocolV2.h [ context: commit ed3ec4c01d17
35 ("msg: Build target 'common' without using namespace in
36 headers") not in octopus ]
37
38CVE: CVE-2020-1759
39Upstream Status: Backport [20b7bb685c5ea74c651ca1ea547ac66b0fee7035]
40
41Signed-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
49diff --git a/src/msg/async/ProtocolV2.cc b/src/msg/async/ProtocolV2.cc
50index 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 &timestamp) {
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 "
159diff --git a/src/msg/async/ProtocolV2.h b/src/msg/async/ProtocolV2.h
160index 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 &timestamp);
179 void handle_message_ack(uint64_t seq);
180
181 CONTINUATION_DECL(ProtocolV2, _wait_for_peer_banner);
182diff --git a/src/msg/async/crypto_onwire.cc b/src/msg/async/crypto_onwire.cc
183index 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");
238diff --git a/src/msg/async/crypto_onwire.h b/src/msg/async/crypto_onwire.h
239index 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--
2552.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 @@
1From dfd1d81cec62e21e21696dc87d4db5f920e51a67 Mon Sep 17 00:00:00 2001
2From: Ilya Dryomov <idryomov@gmail.com>
3Date: Fri, 6 Mar 2020 20:16:45 +0100
4Subject: [PATCH] msg/async/crypto_onwire: fix endianness of nonce_t
5
6As a AES-GCM IV, nonce_t is implicitly shared between server and
7client. Currently, if their endianness doesn't match, they are unable
8to communicate in secure mode because each gets its own idea of what
9the next nonce should be after the counter is incremented.
10
11Several RFCs state that the nonce counter should be BE, but since we
12use LE for everything on-disk and on-wire, make it LE.
13
14Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
15Reviewed-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
16Reviewed-by: Sage Weil <sage@redhat.com>
17
18CVE: CVE-2020-1759
19Upstream Status: Backport [dfd1d81cec62e21e21696dc87d4db5f920e51a67]
20
21Signed-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
26diff --git a/src/msg/async/crypto_onwire.cc b/src/msg/async/crypto_onwire.cc
27index 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--
602.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 @@
1From 92da834cababc4dddd5dbbab5837310478d1e6d4 Mon Sep 17 00:00:00 2001
2From: Abhishek Lekshmanan <abhishek@suse.com>
3Date: Fri, 27 Mar 2020 19:29:01 +0100
4Subject: [PATCH] rgw: EPERM to ERR_INVALID_REQUEST
5
6As per Robin's comments and S3 spec
7
8Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
9
10CVE: CVE-2020-1760
11Upstream Status: Backport [92da834cababc4dddd5dbbab5837310478d1e6d4]
12
13Signed-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
18diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
19index 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--
322.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 @@
1From be7679007c3dfab3e19c22c38c36ccac91828e3b Mon Sep 17 00:00:00 2001
2From: "Robin H. Johnson" <rjohnson@digitalocean.com>
3Date: Fri, 27 Mar 2020 20:48:13 +0100
4Subject: [PATCH] rgw: reject control characters in response-header actions
5
6S3 GetObject permits overriding response header values, but those inputs
7need to be validated to insure only characters that are valid in an HTTP
8header value are present.
9
10Credit: Initial vulnerability discovery by William Bowling (@wcbowling)
11Credit: Further vulnerability discovery by Robin H. Johnson <rjohnson@digitalocean.com>
12Signed-off-by: Robin H. Johnson <rjohnson@digitalocean.com>
13
14CVE: CVE-2020-1760
15Upstream Status: Backport [be7679007c3dfab3e19c22c38c36ccac91828e3b]
16
17Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
18---
19 src/rgw/rgw_rest_s3.cc | 22 ++++++++++++++++++++++
20 1 file changed, 22 insertions(+)
21
22diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
23index 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--
632.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 @@
1From 8f90658c731499722d5f4393c8ad70b971d05f77 Mon Sep 17 00:00:00 2001
2From: Matt Benjamin <mbenjamin@redhat.com>
3Date: Fri, 27 Mar 2020 18:13:48 +0100
4Subject: [PATCH] rgw: reject unauthenticated response-header actions
5
6Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
7Reviewed-by: Casey Bodley <cbodley@redhat.com>
8(cherry picked from commit d8dd5e513c0c62bbd7d3044d7e2eddcd897bd400)
9
10CVE: CVE-2020-1760
11Upstream Status: Backport [8f90658c731499722d5f4393c8ad70b971d05f77]
12
13Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
14---
15 src/rgw/rgw_rest_s3.cc | 5 +++++
16 1 file changed, 5 insertions(+)
17
18diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
19index 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--
352.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 @@
1From ddbac9b2779172876ebd2d26b68b04b02350a125 Mon Sep 17 00:00:00 2001
2From: Josh Durgin <jdurgin@redhat.com>
3Date: Thu, 23 Apr 2020 00:22:10 -0400
4Subject: [PATCH 2/3] mon: enforce caps for pre-octopus client tell commands
5
6This affects only the commands whitelisted here - in particular
7injectargs requires write access to the monitors.
8
9Signed-off-by: Josh Durgin <jdurgin@redhat.com>
10
11Upstream-status: Backport
12[https://github.com/ceph/ceph/commit/fc5e56b75a97c4652c87e9959aad1c4dec45010d]
13
14Signed-off-by: Liu Haitao <haitao.liu@windriver.com>
15---
16 src/mon/Monitor.cc | 56 +++++++++++++++++++++++-----------------------
17 1 file changed, 28 insertions(+), 28 deletions(-)
18
19diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
20index 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--
942.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 @@
1From 56800925651857821034ac9c8ec82d45635cc3b8 Mon Sep 17 00:00:00 2001
2From: Josh Durgin <jdurgin@redhat.com>
3Date: Wed, 13 May 2020 21:34:56 -0700
4Subject: [PATCH 3/3] PendingReleaseNotes: note about security fix
5
6Signed-off-by: Josh Durgin <jdurgin@redhat.com>
7
8Upstream-status: Backport
9[https://github.com/ceph/ceph/commit/06f239fc35f35865d2cf92dda1ac8f4d5fe82bde]
10
11Signed-off-by: Liu Haitao <haitao.liu@windriver.com>
12---
13 PendingReleaseNotes | 2 ++
14 1 file changed, 2 insertions(+)
15
16diff --git a/PendingReleaseNotes b/PendingReleaseNotes
17index 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--
302.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
27SRC_URI[md5sum] = "1f9af648b4c6d19975aab2583ab99710" 19SRC_URI[md5sum] = "cab93dadfe38888561d390fd58b8c947"
28SRC_URI[sha256sum] = "4292c473d1714a6602c525d7582e4e03ec608f0a1cbc0dd338207e5c7068e0d3" 20SRC_URI[sha256sum] = "64c5eaf8c1e4092e59bc538e9241b6d5cf4ffca92563031abbea8b37b4cab9da"
29SRC_URI[sha1sum] = "7158806ece1483fcccdf1172c20cc34d9401c543" 21SRC_URI[sha1sum] = "77b60c3775cd6e38f2d07870aee550368105c74b"
30SRC_URI[sha384sum] = "20e996dbf30d1e33a6d6aae36960190125ce263d306415bcec5d2b3032b8b8f730deeba3ca318576573127d08909404a" 22SRC_URI[sha384sum] = "2173c5176e9ff3745e4bc493585a8cf14e9e7737cf575551a010b7b84cd6b88b378dc93e6509b3a696732c51f530fa60"
31SRC_URI[sha512sum] = "07a3ff2ccf1a3abac652ff8c5f1611e7c628fcedcb280adc6cd49792b46fa50c7c29437dc57c2c4a6af708a6833abf8c1a386ef2142d30bd5e1f214ba7aec4f2" 23SRC_URI[sha512sum] = "66c7322575165b4747955ac9de34f9f9e2d4361c8cd8498819383883045601b92f786c4336c79369d6f019db1c4524c492faa40cdceed7fc1b2b373ca6ab5065"
32 24
33DEPENDS = "boost bzip2 curl expat gperf-native \ 25DEPENDS = "boost bzip2 curl expat gperf-native \
34 keyutils libaio libibverbs lz4 \ 26 keyutils libaio libibverbs lz4 \