From 2ed63228ac29a4f12be72afb6d34660d434d8d4b Mon Sep 17 00:00:00 2001 From: wangzengliang Date: Wed, 20 Apr 2022 09:58:43 +0800 Subject: [PATCH] fix CVE-2021-20288 --- 0025-CVE-2021-20288.patch | 209 ++++++++++++++++++++++++++++++++++++++ ceph.spec | 6 +- 2 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 0025-CVE-2021-20288.patch diff --git a/0025-CVE-2021-20288.patch b/0025-CVE-2021-20288.patch new file mode 100644 index 0000000..b82539a --- /dev/null +++ b/0025-CVE-2021-20288.patch @@ -0,0 +1,209 @@ +From 695e23cea1a9b9e03c53c44b3468032b8a6aff7f Mon Sep 17 00:00:00 2001 +From: wangzengliang +Date: Wed, 20 Apr 2022 09:51:54 +0800 +Subject: [PATCH] CVE-2021-20288 + +--- + src/auth/cephx/CephxKeyServer.cc | 43 +++++++++++++++++---------- + src/auth/cephx/CephxKeyServer.h | 8 ++--- + src/auth/cephx/CephxServiceHandler.cc | 21 +++++++------ + 3 files changed, 44 insertions(+), 28 deletions(-) + +diff --git a/src/auth/cephx/CephxKeyServer.cc b/src/auth/cephx/CephxKeyServer.cc +index e06de660..016ebebe 100644 +--- a/src/auth/cephx/CephxKeyServer.cc ++++ b/src/auth/cephx/CephxKeyServer.cc +@@ -22,7 +22,8 @@ + #define dout_prefix *_dout << "cephx keyserverdata: " + + bool KeyServerData::get_service_secret(CephContext *cct, uint32_t service_id, +- ExpiringCryptoKey& secret, uint64_t& secret_id) const ++ ExpiringCryptoKey& secret, uint64_t& secret_id, ++ double& ttl) const + { + map::const_iterator iter = + rotating_secrets.find(service_id); +@@ -38,14 +39,23 @@ bool KeyServerData::get_service_secret(CephContext *cct, uint32_t service_id, + secrets.secrets.begin(); + if (secrets.secrets.size() > 1) + ++riter; +- +- if (riter->second.expiration < ceph_clock_now()) ++ utime_t now = ceph_clock_now(); ++ if (riter->second.expiration < now) + ++riter; // "current" key has expired, use "next" key instead + + secret_id = riter->first; + secret = riter->second; +- ldout(cct, 30) << "get_service_secret service " << ceph_entity_type_name(service_id) +- << " id " << secret_id << " " << secret << dendl; ++ // ttl may have just been increased by user ++ // cap it by expiration of "next" key to prevent handing out a ticket ++ // with a bogus, possibly way into the future, validity ++ ttl = service_id == CEPH_ENTITY_TYPE_AUTH ? ++ cct->_conf->auth_mon_ticket_ttl : cct->_conf->auth_service_ticket_ttl; ++ ttl = min(ttl, static_cast( ++ secrets.secrets.rbegin()->second.expiration - now)); ++ ldout(cct, 30) << " service " ++ << ceph_entity_type_name(service_id) << " secret_id " ++ << secret_id << " " << riter->second << " ttl " << ttl ++ << dendl; + return true; + } + +@@ -53,8 +63,9 @@ bool KeyServerData::get_service_secret(CephContext *cct, uint32_t service_id, + CryptoKey& secret, uint64_t& secret_id) const + { + ExpiringCryptoKey e; +- +- if (!get_service_secret(cct, service_id, e, secret_id)) ++ ++ auto iter = rotating_secrets.find(service_id); ++ if (iter == rotating_secrets.end()) + return false; + + secret = e.key; +@@ -234,15 +245,15 @@ bool KeyServer::get_caps(const EntityName& name, const string& type, + } + + bool KeyServer::get_service_secret(uint32_t service_id, +- ExpiringCryptoKey& secret, uint64_t& secret_id) const ++ ExpiringCryptoKey& secret, uint64_t& secret_id, double& ttl) const + { + Mutex::Locker l(lock); + +- return data.get_service_secret(cct, service_id, secret, secret_id); ++ return data.get_service_secret(cct, service_id, secret, secret_id, ttl); + } + + bool KeyServer::get_service_secret(uint32_t service_id, +- CryptoKey& secret, uint64_t& secret_id) const ++ CryptoKey& secret, uint64_t& secret_id, double& ttl) const + { + Mutex::Locker l(lock); + +@@ -422,11 +433,12 @@ bool KeyServer::get_service_caps(const EntityName& name, uint32_t service_id, + + + int KeyServer::_build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, +- CephXSessionAuthInfo& info) ++ CephXSessionAuthInfo& info, double& ttl) + { + info.service_id = service_id; + info.ticket = auth_ticket_info.ticket; +- info.ticket.init_timestamps(ceph_clock_now(), cct->_conf->auth_service_ticket_ttl); ++ info.ticket.init_timestamps(ceph_clock_now(), ttl); ++ info.validity.set_from_double(ttl); + + generate_secret(info.session_key); + +@@ -443,13 +455,14 @@ int KeyServer::_build_session_auth_info(uint32_t service_id, CephXServiceTicketI + int KeyServer::build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, + CephXSessionAuthInfo& info) + { +- if (!get_service_secret(service_id, info.service_secret, info.secret_id)) { ++ double ttl; ++ if (!get_service_secret(service_id, info.service_secret, info.secret_id, ttl)) { + return -EPERM; + } + + Mutex::Locker l(lock); + +- return _build_session_auth_info(service_id, auth_ticket_info, info); ++ return _build_session_auth_info(service_id, auth_ticket_info, info, ttl); + } + + int KeyServer::build_session_auth_info(uint32_t service_id, CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info, +@@ -459,6 +472,6 @@ int KeyServer::build_session_auth_info(uint32_t service_id, CephXServiceTicketIn + info.secret_id = secret_id; + + Mutex::Locker l(lock); +- return _build_session_auth_info(service_id, auth_ticket_info, info); ++ return _build_session_auth_info(service_id, auth_ticket_info, info, cct->_conf->auth_service_ticket_ttl); + } + +diff --git a/src/auth/cephx/CephxKeyServer.h b/src/auth/cephx/CephxKeyServer.h +index ff91e96d..20ea843a 100644 +--- a/src/auth/cephx/CephxKeyServer.h ++++ b/src/auth/cephx/CephxKeyServer.h +@@ -89,7 +89,7 @@ struct KeyServerData { + } + + bool get_service_secret(CephContext *cct, uint32_t service_id, +- ExpiringCryptoKey& secret, uint64_t& secret_id) const; ++ ExpiringCryptoKey& secret, uint64_t& secret_id, double& ttl) const; + bool get_service_secret(CephContext *cct, uint32_t service_id, + CryptoKey& secret, uint64_t& secret_id) const; + bool get_service_secret(CephContext *cct, uint32_t service_id, +@@ -193,7 +193,7 @@ class KeyServer : public KeyStore { + bool _check_rotating_secrets(); + void _dump_rotating_secrets(); + int _build_session_auth_info(uint32_t service_id, +- CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info); ++ CephXServiceTicketInfo& auth_ticket_info, CephXSessionAuthInfo& info, double& ttl); + bool _get_service_caps(const EntityName& name, uint32_t service_id, + AuthCapsInfo& caps) const; + public: +@@ -213,9 +213,9 @@ public: + + /* get current secret for specific service type */ + bool get_service_secret(uint32_t service_id, ExpiringCryptoKey& service_key, +- uint64_t& secret_id) const; ++ uint64_t& secret_id, double& ttl) const; + bool get_service_secret(uint32_t service_id, CryptoKey& service_key, +- uint64_t& secret_id) const; ++ uint64_t& secret_id, double& ttl) const; + bool get_service_secret(uint32_t service_id, uint64_t secret_id, + CryptoKey& secret) const override; + +diff --git a/src/auth/cephx/CephxServiceHandler.cc b/src/auth/cephx/CephxServiceHandler.cc +index b06e0080..9211ae71 100644 +--- a/src/auth/cephx/CephxServiceHandler.cc ++++ b/src/auth/cephx/CephxServiceHandler.cc +@@ -106,23 +106,27 @@ int CephxServiceHandler::handle_request(bufferlist::iterator& indata, bufferlist + should_enc_ticket = true; + } + +- info.ticket.init_timestamps(ceph_clock_now(), cct->_conf->auth_mon_ticket_ttl); ++ double ttl; ++ if (!key_server->get_service_secret(CEPH_ENTITY_TYPE_AUTH, ++ info.service_secret, info.secret_id, ++ ttl)) { ++ ldout(cct, 0) << " could not get service secret for auth subsystem" << dendl; ++ ret = -EIO; ++ break; ++ } ++ ++ info.service_id = CEPH_ENTITY_TYPE_AUTH; + info.ticket.name = entity_name; + info.ticket.global_id = global_id; ++ info.ticket.init_timestamps(ceph_clock_now(), ttl); ++ info.validity.set_from_double(ttl); + info.ticket.auid = eauth.auid; +- info.validity += cct->_conf->auth_mon_ticket_ttl; + + if (auid) *auid = eauth.auid; + + key_server->generate_secret(session_key); + + info.session_key = session_key; +- info.service_id = CEPH_ENTITY_TYPE_AUTH; +- if (!key_server->get_service_secret(CEPH_ENTITY_TYPE_AUTH, info.service_secret, info.secret_id)) { +- ldout(cct, 0) << " could not get service secret for auth subsystem" << dendl; +- ret = -EIO; +- break; +- } + + vector info_vec; + info_vec.push_back(info); +@@ -182,7 +186,6 @@ int CephxServiceHandler::handle_request(bufferlist::iterator& indata, bufferlist + service_err = r; + continue; + } +- info.validity += cct->_conf->auth_service_ticket_ttl; + info_vec.push_back(info); + ++found_services; + } +-- +2.30.0 + diff --git a/ceph.spec b/ceph.spec index 78203f5..7ddf0aa 100644 --- a/ceph.spec +++ b/ceph.spec @@ -68,7 +68,7 @@ ################################################################################# Name: ceph Version: 12.2.8 -Release: 20 +Release: 21 Epoch: 2 # define _epoch_prefix macro which will expand to the empty string if epoch is @@ -108,6 +108,7 @@ Patch21: 0021-common-mempool-Add-test-for-mempool-shards.patch Patch22: 0022-common-mempool-Modify-shard-selection-function.patch Patch23: 0023-common-mempool-only-fail-tests-if-sharding-is-very-b.patch Patch24: 0024-CVE-2021-3979.patch +Patch25: 0025-CVE-2021-20288.patch Requires: glibc >= 2.28-66 @@ -1856,6 +1857,9 @@ exit 0 %changelog +* Wed Apr 20 2022 wangzengliang - 1:12.2.8-21 +- fix CVE-2021-20288 + * Sun Jan 29 2022 luo rixin - 1:12.2.8-20 - fix CVE-2021-3979 -- Gitee