diff options
Diffstat (limited to '')
-rw-r--r-- | src/mds/Beacon.cc | 24 | ||||
-rw-r--r-- | src/mds/MDSAuthCaps.h | 17 | ||||
-rw-r--r-- | src/mds/Server.cc | 23 | ||||
-rw-r--r-- | src/mds/SessionMap.cc | 1 | ||||
-rw-r--r-- | src/mds/SessionMap.h | 12 | ||||
-rw-r--r-- | src/mds/mdstypes.cc | 26 | ||||
-rw-r--r-- | src/mds/mdstypes.h | 3 |
7 files changed, 84 insertions, 22 deletions
diff --git a/src/mds/Beacon.cc b/src/mds/Beacon.cc index 5dd319a14..b67e0a31b 100644 --- a/src/mds/Beacon.cc +++ b/src/mds/Beacon.cc @@ -484,6 +484,30 @@ void Beacon::notify_health(MDSRank const *mds) health.metrics.push_back(m); } + // Report a health warning if clients have broken root_squash + if (auto c = mds->sessionmap.num_broken_root_squash_clients(); c > 0) { + std::vector<MDSHealthMetric> metrics; + + for (auto&& session : mds->sessionmap.get_broken_root_squash_clients()) { + CachedStackStringStream css; + *css << "Client " << session->get_human_name() << " has broken root_squash implementation"; + MDSHealthMetric m(MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH, HEALTH_ERR, css->strv()); + m.metadata["client_id"] = stringify(session->get_client()); + metrics.emplace_back(std::move(m)); + } + + if (metrics.size() <= (size_t)g_conf()->mds_health_summarize_threshold) { + health.metrics.insert(std::end(health.metrics), std::make_move_iterator(std::begin(metrics)), std::make_move_iterator(std::end(metrics))); + } else { + CachedStackStringStream css; + *css << "There are " << c << " clients with broken root_squash implementations"; + dout(20) << css->strv() << dendl; + MDSHealthMetric m(MDS_HEALTH_CLIENTS_BROKEN_ROOTSQUASH, HEALTH_ERR, css->strv()); + m.metadata["client_count"] = stringify(c); + health.metrics.push_back(std::move(m)); + } + } + // Report if we have significantly exceeded our cache size limit if (mds->mdcache->cache_overfull()) { CachedStackStringStream css; diff --git a/src/mds/MDSAuthCaps.h b/src/mds/MDSAuthCaps.h index bbb2589b3..f77fd965a 100644 --- a/src/mds/MDSAuthCaps.h +++ b/src/mds/MDSAuthCaps.h @@ -146,6 +146,10 @@ struct MDSCapMatch { */ bool match_path(std::string_view target_path) const; + bool match_fs(std::string_view target_fs) const { + return fs_name == target_fs || fs_name.empty() || fs_name == "*"; + } + void encode(ceph::buffer::list& bl) const { ENCODE_START(1, 1, bl); encode(uid, bl); @@ -261,8 +265,7 @@ public: } for (const MDSCapGrant &g : grants) { - if (g.match.fs_name == fs_name || g.match.fs_name.empty() || - g.match.fs_name == "*") { + if (g.match.match_fs(fs_name)) { if (mask & MAY_READ && g.spec.allow_read()) { return true; } @@ -285,10 +288,12 @@ public: } } - bool root_squash_in_caps() const { - for (const MDSCapGrant &g : grants) { - if (g.match.root_squash) { - return true; + bool root_squash_in_caps(std::string_view fs_name) const { + for (const MDSCapGrant& g : grants) { + if (g.match.match_fs(fs_name)) { + if (g.match.root_squash) { + return true; + } } } return false; diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 48e7b03ae..2f8b376ce 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -717,16 +717,10 @@ void Server::handle_client_session(const cref_t<MClientSession> &m) break; } - if (session->auth_caps.root_squash_in_caps() && !client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK)) { - CachedStackStringStream css; - *css << "client lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK needed to enforce 'root_squash' MDS auth caps"; - send_reject_message(css->strv()); - mds->clog->warn() << "client session (" << session->info.inst - << ") lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK " - << " needed to enforce 'root_squash' MDS auth caps"; - session->clear(); - break; - + std::string_view fs_name = mds->mdsmap->get_fs_name(); + bool client_caps_check = client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK); + if (session->auth_caps.root_squash_in_caps(fs_name) && !client_caps_check) { + mds->sessionmap.add_to_broken_root_squash_clients(session); } // Special case for the 'root' metadata path; validate that the claimed // root is actually within the caps of the session @@ -1573,11 +1567,10 @@ void Server::handle_client_reconnect(const cref_t<MClientReconnect> &m) *css << "missing required features '" << missing_features << "'"; error_str = css->strv(); } - if (session->auth_caps.root_squash_in_caps() && - !session->info.client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK)) { - CachedStackStringStream css; - *css << "client lacks CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK needed to enforce 'root_squash' MDS auth caps"; - error_str = css->strv(); + std::string_view fs_name = mds->mdsmap->get_fs_name(); + bool client_caps_check = session->info.client_metadata.features.test(CEPHFS_FEATURE_MDS_AUTH_CAPS_CHECK); + if (session->auth_caps.root_squash_in_caps(fs_name) && !client_caps_check) { + mds->sessionmap.add_to_broken_root_squash_clients(session); } } diff --git a/src/mds/SessionMap.cc b/src/mds/SessionMap.cc index 9cc2b0138..9bec67c24 100644 --- a/src/mds/SessionMap.cc +++ b/src/mds/SessionMap.cc @@ -705,6 +705,7 @@ void SessionMap::remove_session(Session *s) s->trim_completed_requests(0); s->item_session_list.remove_myself(); + broken_root_squash_clients.erase(s); session_map.erase(s->info.inst.name); dirty_sessions.erase(s->info.inst.name); null_sessions.insert(s->info.inst.name); diff --git a/src/mds/SessionMap.h b/src/mds/SessionMap.h index 360dd66a2..623f20a0e 100644 --- a/src/mds/SessionMap.h +++ b/src/mds/SessionMap.h @@ -682,6 +682,16 @@ public: void remove_session(Session *s); void touch_session(Session *session); + void add_to_broken_root_squash_clients(Session* s) { + broken_root_squash_clients.insert(s); + } + uint64_t num_broken_root_squash_clients() const { + return broken_root_squash_clients.size(); + } + auto const& get_broken_root_squash_clients() const { + return broken_root_squash_clients; + } + Session *get_oldest_session(int state) { auto by_state_entry = by_state.find(state); if (by_state_entry == by_state.end() || by_state_entry->second->empty()) @@ -849,6 +859,8 @@ private: bool validate_and_encode_session(MDSRank *mds, Session *session, bufferlist& bl); void apply_blocklist(const std::set<entity_name_t>& victims); + + std::set<Session*> broken_root_squash_clients; }; std::ostream& operator<<(std::ostream &out, const Session &s); diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc index 044c33459..114ca137b 100644 --- a/src/mds/mdstypes.cc +++ b/src/mds/mdstypes.cc @@ -7,6 +7,10 @@ #include "common/Formatter.h" #include "common/StackStringStream.h" +#include <iostream> +#include <sstream> +#include <string> + const mds_gid_t MDS_GID_NONE = mds_gid_t(0); using std::list; @@ -429,7 +433,7 @@ feature_bitset_t::feature_bitset_t(unsigned long value) } } -feature_bitset_t::feature_bitset_t(const vector<size_t>& array) +void feature_bitset_t::init_array(const vector<size_t>& array) { if (!array.empty()) { size_t n = array.back(); @@ -448,6 +452,26 @@ feature_bitset_t::feature_bitset_t(const vector<size_t>& array) } } +feature_bitset_t::feature_bitset_t(std::string_view str) +{ + std::stringstream ss; + std::vector<size_t> v; + std::string atom; + + ss << str; + while (std::getline(ss, atom, ',')) { + v.push_back(std::stoul(atom)); + } + std::sort(v.begin(), v.end()); + + init_array(v); +} + +feature_bitset_t::feature_bitset_t(const vector<size_t>& array) +{ + init_array(array); +} + feature_bitset_t& feature_bitset_t::operator-=(const feature_bitset_t& other) { for (size_t i = 0; i < _vec.size(); ++i) { diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 3381d44c9..8e7b16761 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -294,6 +294,7 @@ public: feature_bitset_t(const feature_bitset_t& other) : _vec(other._vec) {} feature_bitset_t(feature_bitset_t&& other) : _vec(std::move(other._vec)) {} feature_bitset_t(unsigned long value = 0); + feature_bitset_t(std::string_view); feature_bitset_t(const std::vector<size_t>& array); feature_bitset_t& operator=(const feature_bitset_t& other) { _vec = other._vec; @@ -347,6 +348,8 @@ public: void dump(ceph::Formatter *f) const; void print(std::ostream& out) const; private: + void init_array(const std::vector<size_t>& v); + std::vector<block_type> _vec; }; WRITE_CLASS_ENCODER(feature_bitset_t) |