]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Add multi user support on a unlock claim.
authorChristopher Hoffman <choffman@redhat.com>
Mon, 30 Oct 2023 22:31:45 +0000 (22:31 +0000)
committerChristopher Hoffman <choffman@redhat.com>
Wed, 5 Nov 2025 13:59:33 +0000 (13:59 +0000)
Signed-off-by: Christopher Hoffman <choffman@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/FSCrypt.cc
src/client/FSCrypt.h
src/client/fuse_ll.cc
src/include/cephfs/libcephfs.h
src/libcephfs.cc

index 38d32877d2b9bdf8fb4f17e95ecf6a81f88f9731..d9234ad55576e6a63bd820cdcdea81e964b394b3 100644 (file)
@@ -18271,13 +18271,13 @@ void Client::set_uuid(const std::string& uuid)
 }
 
 int Client::add_fscrypt_key(const char *key_data, int key_len,
-                            ceph_fscrypt_key_identifier *kid)
+                            ceph_fscrypt_key_identifier *kid, int user)
 {
   auto& key_store = fscrypt->get_key_store();
 
   FSCryptKeyHandlerRef kh;
 
-  int r = key_store.create((const char *)key_data, key_len, kh);
+  int r = key_store.create((const char *)key_data, key_len, kh, user);
   if (r < 0) {
     ldout(cct, 0) << __func__ << "(): failed to create a new key: r=" << r << dendl;
     return r;
@@ -18292,11 +18292,11 @@ int Client::add_fscrypt_key(const char *key_data, int key_len,
   return 0;
 }
 
-int Client::remove_fscrypt_key(const ceph_fscrypt_key_identifier& kid)
+int Client::remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user)
 {
   auto& key_store = fscrypt->get_key_store();
 
-  return key_store.invalidate(kid);
+  return key_store.invalidate(kid, user);
 }
 
 int Client::set_fscrypt_policy_v2(int fd, const struct fscrypt_policy_v2& policy)
index b0c67bf8a15417ba8fbadccc5f5caced934b2f7a..438521645ebb08f36e84dc5f41b12d9f5665e8b1 100644 (file)
@@ -380,8 +380,8 @@ public:
   }
 
   /* fscrypt */
-  int add_fscrypt_key(const char *key_data, int key_len, ceph_fscrypt_key_identifier *kid);
-  int remove_fscrypt_key(const ceph_fscrypt_key_identifier& kid);
+  int add_fscrypt_key(const char *key_data, int key_len, ceph_fscrypt_key_identifier *kid, int user = 0);
+  int remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user = 0);
   int set_fscrypt_policy_v2(int fd, const struct fscrypt_policy_v2& policy);
 
   int mds_command(
index c492f60e2adf7b3bfac2c25e86ae1fcc920cc8d8..2a8825dfb6b0cb6bf5eb01628e5dd7c79919f3cb 100644 (file)
@@ -376,7 +376,76 @@ FSCryptKeyRef& FSCryptKeyHandler::get_key()
   return key;
 }
 
-int FSCryptKeyStore::create(const char *k, int klen, FSCryptKeyHandlerRef& key_handler)
+//taken from fs/crypto/keyring.h
+bool FSCryptKeyStore::valid_key_spec(const struct fscrypt_key_specifier& k)
+{
+  if (k.__reserved)
+    return false;
+  return master_key_spec_len(k) != 0;
+}
+
+//taken from fs/crypto/fscrypt_private.h
+int FSCryptKeyStore::master_key_spec_len(const struct fscrypt_key_specifier& spec)
+{
+        switch (spec.type) {
+        case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
+                return FSCRYPT_KEY_DESCRIPTOR_SIZE;
+        case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
+                return FSCRYPT_KEY_IDENTIFIER_SIZE;
+        }
+        return 0;
+}
+
+
+
+int FSCryptKeyStore::maybe_add_user(std::list<int>* users, int user)
+{
+  ldout(cct, 10) << __FILE__ << ":" << __LINE__ << " user=" << user << dendl;
+
+  auto it = std::find(users->begin(), users->end(), user);
+  if (it != users->end()) {
+    ldout(cct, 10) << "maybe_add_user user already added!" << dendl;
+    return -EEXIST;
+  }
+  
+  ldout(cct, 10) << "maybe_add_user is not found!, adding" << dendl;
+  users->push_back(user);
+  ldout(cct, 10) << "maybe_add_user size is now=" << users->size() << dendl;
+  return 0;
+}
+
+int FSCryptKeyStore::maybe_remove_user(struct fscrypt_remove_key_arg* arg, std::list<int>* users, int user)
+{
+  ldout(cct, 10) << __FILE__ << ":" << __LINE__ << " user=" << user << dendl;
+  uint32_t status_flags = 0;
+  int err = 0;
+  bool removed = false;
+  if (!valid_key_spec(arg->key_spec)) {
+    return -EINVAL;
+  }
+
+  auto it = std::find(users->begin(), users->end(), user);
+  if (it != users->end()) {
+    ldout(cct, 10) << "maybe_remove_user, user found removing!" << dendl;
+    removed = true;
+    users->erase(it);
+  } else {
+    return -ENOKEY;
+  }
+  ldout(cct, 10) << "maybe_add_user size is now=" << users->size() << dendl;
+
+  if (users->size() != 0 && removed) {
+
+    //set bits for removed for requested user
+    status_flags |= FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
+    err = -EBUSY;
+  }
+
+  arg->removal_status_flags = status_flags;
+  return err;
+}
+
+int FSCryptKeyStore::create(const char *k, int klen, FSCryptKeyHandlerRef& key_handler, int user)
 {
   auto key = std::make_shared<FSCryptKey>();
 
@@ -384,21 +453,30 @@ int FSCryptKeyStore::create(const char *k, int klen, FSCryptKeyHandlerRef& key_h
   if (r < 0) {
     return r;
   }
-
   std::unique_lock wl{lock};
 
   const auto& id = key->get_identifier();
-  
   auto iter = m.find(id);
   if (iter != m.end()) {
     /* found a key handler entry, check that there is a key there */
     key_handler = iter->second;
-    if (key_handler->get_key()) {
-      return -EEXIST;
+
+    auto& users = key_handler->get_users();
+    r = maybe_add_user(&users, user);
+
+    if (r == -EEXIST) {
+      return 0; //returns 0 regardless
     }
     key_handler->reset(++epoch, key);
   } else {
     key_handler = std::make_shared<FSCryptKeyHandler>(++epoch, key);
+
+    auto& users = key_handler->get_users();
+    r = maybe_add_user(&users, user);
+    if (r == -EEXIST) {
+      return 0; //returns 0 regardless
+    }
+
     m[id] = key_handler;
   }
 
@@ -409,7 +487,7 @@ int FSCryptKeyStore::_find(const struct ceph_fscrypt_key_identifier& id, FSCrypt
 {
   auto iter = m.find(id);
   if (iter == m.end()) {
-    return -ENOENT;
+    return -ENOKEY;
   }
 
   kh = iter->second;
@@ -424,15 +502,25 @@ int FSCryptKeyStore::find(const struct ceph_fscrypt_key_identifier& id, FSCryptK
   return _find(id, kh);
 }
 
-int FSCryptKeyStore::invalidate(const struct ceph_fscrypt_key_identifier& id)
+int FSCryptKeyStore::invalidate(struct fscrypt_remove_key_arg* arg, int user)
 {
   std::unique_lock rl{lock};
 
+  ceph_fscrypt_key_identifier id;
+  int r = id.init(arg->key_spec);
+  if (r < 0) {
+    return r;
+  }
+
   FSCryptKeyHandlerRef kh;
-  int r = _find(id, kh);
-  if (r == -ENOENT) {
-    return 0;
-  } else if (r < 0) {
+  r = _find(id, kh);
+  if (r < 0) {
+    return r;
+  }
+
+  auto& users = kh->get_users();
+  r = maybe_remove_user(arg, &users, user);
+  if (r < 0) {
     return r;
   }
 
index 4e43d57e98dc22ca7e0f7b896a0c6f9c6b5ae239..a39ea8ea2fca9f73ce4ba29218257235cc9f0f97 100644 (file)
@@ -90,7 +90,6 @@ std::ostream& operator<<(std::ostream& out, const ceph_fscrypt_key_identifier& k
 class FSCryptKey {
   bufferlist key;
   ceph_fscrypt_key_identifier identifier;
-
 public:
   int init(const char *k, int klen);
 
@@ -299,6 +298,7 @@ class FSCryptKeyHandler {
   ceph::shared_mutex lock = ceph::make_shared_mutex("FSCryptKeyHandler");
   int64_t epoch = -1;
   FSCryptKeyRef key;
+  std::list<int> users;
 public:
   FSCryptKeyHandler() {}
   FSCryptKeyHandler(int64_t epoch, FSCryptKeyRef k) : epoch(epoch), key(k) {}
@@ -306,6 +306,7 @@ public:
   void reset(int64_t epoch, FSCryptKeyRef k);
 
   int64_t get_epoch();
+  std::list<int>& get_users() { return users; }
   FSCryptKeyRef& get_key();
 };
 
@@ -322,9 +323,13 @@ class FSCryptKeyStore {
 public:
   FSCryptKeyStore(CephContext *_cct) : cct(_cct) {}
 
-  int create(const char *k, int klen, FSCryptKeyHandlerRef& key);
+  bool valid_key_spec(const struct fscrypt_key_specifier& k);
+  int master_key_spec_len(const struct fscrypt_key_specifier& spec);
+  int maybe_add_user(std::list<int>* users, int user);
+  int maybe_remove_user(struct fscrypt_remove_key_arg* arg, std::list<int>* users, int user);
+  int create(const char *k, int klen, FSCryptKeyHandlerRef& key, int user);
   int find(const struct ceph_fscrypt_key_identifier& id, FSCryptKeyHandlerRef& key);
-  int invalidate(const struct ceph_fscrypt_key_identifier& id);
+  int invalidate(struct fscrypt_remove_key_arg* id, int user);
 };
 
 struct FSCryptKeyValidator {
index 4452473a436035b479ca55d0e795f29228b27932..dfd9796f8562da87d74c756e973da17e6c8a1890 100644 (file)
@@ -1013,7 +1013,7 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino,
         break;
       }
 
-      int r = cfuse->client->add_fscrypt_key((const char *)arg->raw, arg->raw_size, nullptr);
+      int r = cfuse->client->add_fscrypt_key((const char *)arg->raw, arg->raw_size, nullptr, ctx->uid);
       if (r < 0) {
         generic_dout(0) << __FILE__ << ":" << __LINE__ << ": failed to create a new key: r=" << r << dendl;
         fuse_reply_err(req, -r);
@@ -1047,13 +1047,12 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino,
       }
 
       /* FIXME: handle busy cases */
-      r = cfuse->client->remove_fscrypt_key(kid);
+      r = cfuse->client->remove_fscrypt_key(arg, ctx->uid);
       if (r < 0) {
         fuse_reply_err(req, -r);
         break;
       }
 
-      arg->removal_status_flags = 0; /* FIXME */
       fuse_reply_ioctl(req, 0, arg, sizeof(*arg));
       break;
     }
@@ -1138,7 +1137,8 @@ static void fuse_ll_ioctl(fuse_req_t req, fuse_ino_t ino,
 
       /* TODO: return correct info */
       arg->status = (found ? FSCRYPT_KEY_STATUS_PRESENT : FSCRYPT_KEY_STATUS_ABSENT);
-      arg->status_flags = (found ? 0x1 : 0); /* FIXME */
+      arg->status_flags = 0;//(found ? 0x1 : 0); /* FIXME */
+      //arg->status_flags = (found ? 0x1 : 0); /* FIXME */
       arg->user_count = !!found; /* FIXME */
 
       fuse_reply_ioctl(req, 0, arg, sizeof(*arg));
index 015ab945966ce1fe7e9a4a5a0e7efaad34c66e6e..e3f3bbd39eb9e5e8e222810893c54dcabdabd34a 100644 (file)
@@ -2021,7 +2021,7 @@ int ceph_add_fscrypt_key(struct ceph_mount_info *cmount,
  * @returns zero on success, other returns a negative error code.
  */
 int ceph_remove_fscrypt_key(struct ceph_mount_info *cmount,
-                            const struct ceph_fscrypt_key_identifier *kid);
+                            struct fscrypt_remove_key_arg *kid);
 
 /**
  * Set encryption policy on a directory.
index 5bf485a7bc414b42a327072dc703fafee2a51d77..9a9e86f52c3939ee96a3b6f29e9da7e252713590 100644 (file)
@@ -2515,12 +2515,12 @@ extern "C" int ceph_add_fscrypt_key(struct ceph_mount_info *cmount,
 }
 
 extern "C" int ceph_remove_fscrypt_key(struct ceph_mount_info *cmount,
-                                       const struct ceph_fscrypt_key_identifier *kid)
+                                       struct fscrypt_remove_key_arg *kid)
 {
   if (!cmount->is_mounted())
     return -CEPHFS_ENOTCONN;
 
-  return cmount->get_client()->remove_fscrypt_key(*kid);
+  return cmount->get_client()->remove_fscrypt_key(kid);
 }
 
 extern "C" int ceph_set_fscrypt_policy_v2(struct ceph_mount_info *cmount,