From f0deab02e044d0a4ed598b5b735a5ca8c571d021 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Wed, 7 Dec 2022 15:03:35 +0800 Subject: [PATCH] client: save the cap_auths in client when session being opened Fixes: https://tracker.ceph.com/issues/57154 Signed-off-by: Xiubo Li (cherry picked from commit 01a93986bff4340b1e8fecfd4e83ad92afc79b5d) Conflicts: src/client/Client.cc: conflict with commit 997b917c84e ("client: always refresh mds feature bits on session open") --- src/client/Client.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++ src/client/Client.h | 6 +++++ 2 files changed, 67 insertions(+) diff --git a/src/client/Client.cc b/src/client/Client.cc index 84c4715caf5..95ebb50046b 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -2425,6 +2425,7 @@ void Client::handle_client_session(const MConstRef& m) session->seq = m->get_seq(); reinit_mds_features(session.get(), m); + cap_auths = std::move(m->cap_auths); renew_caps(session.get()); session->state = MetaSession::STATE_OPEN; @@ -5884,6 +5885,66 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, const M _try_to_trim_inode(in, true); } +int Client::mds_check_access(std::string& path, const UserPerm& perms, int mask) +{ + const gid_t *gids; + int count = perms.get_gids(&gids); + std::vector gid_list; + bool root_squash_perms = true; + MDSCapAuth *rw_perms_s = nullptr; + + ldout(cct, 25) << __func__ << " path " << path << ", uid " << perms.uid() + << ", gid " << perms.gid() << ", mask " << mask << dendl; + + if (count) { + gid_list.reserve(count); + for (int i = 0; i < count; ++i) { + gid_list.push_back(gids[i]); + } + } + + for (auto& s: cap_auths) { + ldout(cct, 20) << __func__ << " auth match path " << s.match.path << " r: " << s.readable + << " w: " << s.writeable << dendl; + ldout(cct, 20) << " match.uid " << s.match.uid << dendl; + if (s.match.match(path, perms.uid(), perms.gid(), &gid_list)) { + ldout(cct, 20) << " is matched" << dendl; + // always follow the last auth caps' permision + root_squash_perms = true; + rw_perms_s = nullptr; + + if ((mask & MAY_WRITE) && s.writeable && + s.match.root_squash && ((perms.uid() == 0) || (perms.gid() == 0))) { + root_squash_perms = false; + } + + if (((mask & MAY_WRITE) && !s.writeable) || + ((mask & MAY_READ) && !s.readable)) { + rw_perms_s = &s; + } + } else { + ldout(cct, 20) << " is mismatched" << dendl; + } + } + + if (root_squash_perms && rw_perms_s == nullptr) { + return 0; + } + + if (!root_squash_perms) { + ldout(cct, 10) << __func__ << " permission denied, root_squash is enabled and user" + << " (uid " << perms.uid() << ", gid " << perms.gid() + << ") isn't allowed to write" << dendl; + } + if (rw_perms_s) { + ldout(cct, 10) << __func__ << " permission denied, mds auth caps readable/writeable:" + << rw_perms_s->readable << "/" << rw_perms_s->writeable << ", request r/w:" + << !!(mask & MAY_READ) << "/" << !!(mask & MAY_WRITE) << dendl; + } + + return -CEPHFS_EACCES; +} + int Client::inode_permission(Inode *in, const UserPerm& perms, unsigned want) { if (perms.uid() == 0) { diff --git a/src/client/Client.h b/src/client/Client.h index ae94b3fb536..b7c3b105fd2 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -32,6 +32,7 @@ #include "include/unordered_set.h" #include "include/cephfs/metrics/Types.h" #include "mds/mdstypes.h" +#include "mds/MDSAuthCaps.h" #include "include/cephfs/types.h" #include "msg/Dispatcher.h" #include "msg/MessageRef.h" @@ -551,6 +552,9 @@ public: mode_t mode=0, const std::map &metadata={}); int rmsnap(const char *path, const char *name, const UserPerm& perm, bool check_perms=false); + // cephx mds auth caps checking + int mds_check_access(std::string& path, const UserPerm& perms, int mask); + // Inode permission checking int inode_permission(Inode *in, const UserPerm& perms, unsigned want); @@ -1630,6 +1634,8 @@ private: uint64_t nr_metadata_request = 0; uint64_t nr_read_request = 0; uint64_t nr_write_request = 0; + + std::vector cap_auths; }; /** -- 2.39.5