]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
libcephfs_proxy: implement support for fscrypt 64743/head
authorXavi Hernandez <xhernandez@gmail.com>
Thu, 18 Sep 2025 10:39:30 +0000 (12:39 +0200)
committerXavi Hernandez <xhernandez@gmail.com>
Tue, 13 Jan 2026 17:32:31 +0000 (18:32 +0100)
Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
src/libcephfs_proxy/libcephfs_proxy.c
src/libcephfs_proxy/libcephfsd.c
src/libcephfs_proxy/proxy_requests.h

index d4f4caa31108028e79a7512f1976ef1adce57b38..e6996232436d3b75bdf15f62935d5f3bcb24b6dc 100644 (file)
@@ -1,6 +1,8 @@
 
 #include <stdlib.h>
 
+#include <linux/fscrypt.h>
+
 #include "include/cephfs/libcephfs.h"
 
 #include "proxy_log.h"
@@ -1087,3 +1089,91 @@ __public int64_t ceph_ll_nonblocking_readv_writev(
 
        return ans.res;
 }
+
+__public int32_t ceph_add_fscrypt_key(struct ceph_mount_info *cmount,
+                                     const char *key_data, int32_t key_len,
+                                     char *kid, int32_t user)
+{
+       CEPH_REQ(ceph_add_fscrypt_key, req, 1, ans, 1);
+
+       req.user = user;
+       req.kid = FSCRYPT_KEY_IDENTIFIER_SIZE;
+
+       CEPH_BUFF_ADD(req, key_data, key_len);
+
+       CEPH_BUFF_ADD(ans, kid, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_ADD_FSCRYPT_KEY, req, ans);
+}
+
+__public int32_t ceph_remove_fscrypt_key(struct ceph_mount_info *cmount,
+                                        struct fscrypt_remove_key_arg *arg,
+                                        int32_t user)
+{
+       CEPH_REQ(ceph_remove_fscrypt_key, req, 1, ans, 1);
+
+       req.user = user;
+       req.arg = sizeof(struct fscrypt_remove_key_arg);
+
+       CEPH_BUFF_ADD(req, arg, sizeof(struct fscrypt_remove_key_arg));
+
+       CEPH_BUFF_ADD(ans, arg, sizeof(struct fscrypt_remove_key_arg));
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_REMOVE_FSCRYPT_KEY, req, ans);
+}
+
+__public int32_t ceph_get_fscrypt_key_status(
+       struct ceph_mount_info *cmount, struct fscrypt_get_key_status_arg *arg)
+{
+       CEPH_REQ(ceph_get_fscrypt_key_status, req, 1, ans, 1);
+
+       req.arg = sizeof(struct fscrypt_get_key_status_arg);
+
+       CEPH_BUFF_ADD(req, arg, sizeof(struct fscrypt_get_key_status_arg));
+
+       CEPH_BUFF_ADD(ans, arg, sizeof(struct fscrypt_get_key_status_arg));
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_REMOVE_FSCRYPT_KEY, req, ans);
+}
+
+__public int32_t ceph_ll_set_fscrypt_policy_v2(
+       struct ceph_mount_info *cmount, Inode *in,
+       const struct fscrypt_policy_v2 *policy)
+{
+       CEPH_REQ(ceph_ll_set_fscrypt_policy_v2, req, 1, ans, 0);
+
+       req.inode = ptr_value(in);
+       req.policy = sizeof(struct fscrypt_policy_v2);
+
+       CEPH_BUFF_ADD(req, policy, sizeof(struct fscrypt_policy_v2));
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_SET_FSCRYPT_POLICY_V2, req,
+                           ans);
+}
+
+__public int32_t ceph_ll_get_fscrypt_policy_v2(struct ceph_mount_info *cmount,
+                                              Inode *in,
+                                              struct fscrypt_policy_v2 *policy)
+{
+       CEPH_REQ(ceph_ll_get_fscrypt_policy_v2, req, 0, ans, 1);
+
+       req.inode = ptr_value(in);
+       req.policy = sizeof(struct fscrypt_policy_v2);
+
+       CEPH_BUFF_ADD(ans, policy, sizeof(struct fscrypt_policy_v2));
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_GET_FSCRYPT_POLICY_V2, req,
+                           ans);
+}
+
+__public int32_t ceph_ll_is_encrypted(struct ceph_mount_info *cmount,
+                                     Inode *in, char *enctag)
+{
+       CEPH_REQ(ceph_ll_is_encrypted, req, 1, ans, 0);
+
+       req.inode = ptr_value(in);
+
+       CEPH_STR_ADD(req, tag, enctag);
+
+       return CEPH_PROCESS(cmount, LIBCEPHFSD_OP_LL_IS_ENCRYPTED, req, ans);
+}
index 64a3f888cd8653a728c5dffdff6236d662807d46..b920856cb8852cc4673ec3b5b31ac4f6559b0494 100644 (file)
@@ -8,6 +8,8 @@
 #include <string.h>
 #include <stdarg.h>
 
+#include <linux/fscrypt.h>
+
 #include "include/cephfs/libcephfs.h"
 
 #include "proxy_manager.h"
@@ -1821,6 +1823,190 @@ done:
        return CEPH_COMPLETE(client, err, ans);
 }
 
+static int32_t libcephfsd_add_fscrypt_key(proxy_client_t *client,
+                                         proxy_req_t *req, const void *data,
+                                         int32_t data_size)
+{
+       CEPH_DATA(ceph_add_fscrypt_key, ans, 1);
+       char kid[FSCRYPT_KEY_IDENTIFIER_SIZE];
+       proxy_mount_t *mount;
+       uint32_t user;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->add_fscrypt_key.cmount,
+                       (void **)&mount);
+       if ((err >= 0) &&
+           (req->add_fscrypt_key.kid != sizeof(kid))) {
+               err = proxy_log(LOG_ERR, EINVAL, "Invalid size of key id");
+       }
+       if (err >= 0) {
+               user = req->add_fscrypt_key.user;
+
+               CEPH_BUFF_ADD(ans, kid, sizeof(kid));
+
+               err = ceph_add_fscrypt_key(proxy_cmount(mount), data,
+                                          req->add_fscrypt_key.key, kid,
+                                          user);
+               TRACE("add_fscrypt_key(%p, %u) -> %d", mount, user, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
+static int32_t libcephfsd_remove_fscrypt_key(proxy_client_t *client,
+                                            proxy_req_t *req, const void *data,
+                                            int32_t data_size)
+{
+       CEPH_DATA(ceph_remove_fscrypt_key, ans, 1);
+       proxy_mount_t *mount;
+       uint32_t user;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->remove_fscrypt_key.cmount,
+                       (void **)&mount);
+       if ((err >= 0) &&
+           (req->remove_fscrypt_key.arg !=
+            sizeof(struct fscrypt_remove_key_arg))) {
+               err = proxy_log(LOG_ERR, EINVAL,
+                               "Invalid size of key remove arg");
+       }
+       if (err >= 0) {
+               user = req->remove_fscrypt_key.user;
+
+               CEPH_BUFF_ADD(ans, data, sizeof(struct fscrypt_remove_key_arg));
+
+               err = ceph_remove_fscrypt_key(
+                       proxy_cmount(mount),
+                       (struct fscrypt_remove_key_arg *)data, user);
+               TRACE("remove_fscrypt_key(%p, %u) -> %d", mount, user, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
+static int32_t libcephfsd_get_fscrypt_key_status(proxy_client_t *client,
+                                                proxy_req_t *req,
+                                                const void *data,
+                                                int32_t data_size)
+{
+       CEPH_DATA(ceph_get_fscrypt_key_status, ans, 1);
+       proxy_mount_t *mount;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->get_fscrypt_key_status.cmount,
+                       (void **)&mount);
+       if ((err >= 0) &&
+           (req->get_fscrypt_key_status.arg !=
+            sizeof(struct fscrypt_get_key_status_arg))) {
+               err = proxy_log(LOG_ERR, EINVAL,
+                               "Invalid size of key status arg");
+       }
+       if (err >= 0) {
+               CEPH_BUFF_ADD(ans, data,
+                             sizeof(struct fscrypt_get_key_status_arg));
+
+               err = ceph_get_fscrypt_key_status(
+                       proxy_cmount(mount),
+                       (struct fscrypt_get_key_status_arg *)data);
+               TRACE("get_fscrypt_key_status(%p) -> %d", mount, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
+static int32_t libcephfsd_ll_set_fscrypt_policy_v2(proxy_client_t *client,
+                                                  proxy_req_t *req,
+                                                  const void *data,
+                                                  int32_t data_size)
+{
+       CEPH_DATA(ceph_ll_set_fscrypt_policy_v2, ans, 0);
+       proxy_mount_t *mount;
+       Inode *inode;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->ll_set_fscrypt_policy_v2.cmount,
+                       (void **)&mount);
+       if (err >= 0) {
+               err = ptr_check(&client->random,
+                               req->ll_set_fscrypt_policy_v2.inode,
+                               (void **)&inode);
+       }
+       if ((err >= 0) &&
+           (req->ll_set_fscrypt_policy_v2.policy !=
+            sizeof(struct fscrypt_policy_v2))) {
+               err = proxy_log(LOG_ERR, EINVAL,
+                               "Invalid size of fscrypt_policy_v2");
+       }
+       if (err >= 0) {
+               err = ceph_ll_set_fscrypt_policy_v2(proxy_cmount(mount), inode,
+                                                   data);
+               TRACE("ll_set_fscrypt_policy_v2(%p) -> %d", mount, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
+static int32_t libcephfsd_ll_get_fscrypt_policy_v2(proxy_client_t *client,
+                                                  proxy_req_t *req,
+                                                  const void *data,
+                                                  int32_t data_size)
+{
+       CEPH_DATA(ceph_ll_get_fscrypt_policy_v2, ans, 1);
+       struct fscrypt_policy_v2 policy;
+       proxy_mount_t *mount;
+       Inode *inode;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->ll_get_fscrypt_policy_v2.cmount,
+                       (void **)&mount);
+       if (err >= 0) {
+               err = ptr_check(&client->random,
+                               req->ll_get_fscrypt_policy_v2.inode,
+                               (void **)&inode);
+       }
+       if ((err >= 0) &&
+           (req->ll_get_fscrypt_policy_v2.policy !=
+            sizeof(struct fscrypt_policy_v2))) {
+               err = proxy_log(LOG_ERR, EINVAL,
+                               "Invalid size of fscrypt_policy_v2");
+       }
+       if (err >= 0) {
+               CEPH_BUFF_ADD(ans, &policy, sizeof(policy));
+
+               err = ceph_ll_get_fscrypt_policy_v2(proxy_cmount(mount), inode,
+                                                   &policy);
+               TRACE("ll_get_fscrypt_policy_v2(%p) -> %d", mount, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
+static int32_t libcephfsd_ll_is_encrypted(proxy_client_t *client,
+                                         proxy_req_t *req, const void *data,
+                                         int32_t data_size)
+{
+       CEPH_DATA(ceph_ll_is_encrypted, ans, 0);
+       proxy_mount_t *mount;
+       Inode *inode;
+       char *tag;
+       int32_t err;
+
+       err = ptr_check(&client->random, req->ll_is_encrypted.cmount,
+                       (void **)&mount);
+       if (err >= 0) {
+               err = ptr_check(&client->random, req->ll_is_encrypted.inode,
+                               (void **)&inode);
+       }
+       if (err >= 0) {
+               tag = (char *)CEPH_STR_GET(req->ll_is_encrypted, tag, data);
+
+               err = ceph_ll_is_encrypted(proxy_cmount(mount), inode, tag);
+               TRACE("ll_is_encrypted(%p) -> %d", mount, err);
+       }
+
+       return CEPH_COMPLETE(client, err, ans);
+}
+
 static proxy_handler_t libcephfsd_handlers[LIBCEPHFSD_OP_TOTAL_OPS] = {
        [LIBCEPHFSD_OP_VERSION] = libcephfsd_version,
        [LIBCEPHFSD_OP_USERPERM_NEW] = libcephfsd_userperm_new,
@@ -1870,6 +2056,15 @@ static proxy_handler_t libcephfsd_handlers[LIBCEPHFSD_OP_TOTAL_OPS] = {
        [LIBCEPHFSD_OP_LL_RELEASEDIR] = libcephfsd_ll_releasedir,
        [LIBCEPHFSD_OP_MOUNT_PERMS] = libcephfsd_mount_perms,
        [LIBCEPHFSD_OP_LL_NONBLOCKING_RW] = libcephfsd_ll_nonblocking_rw,
+       [LIBCEPHFSD_OP_ADD_FSCRYPT_KEY] = libcephfsd_add_fscrypt_key,
+       [LIBCEPHFSD_OP_REMOVE_FSCRYPT_KEY] = libcephfsd_remove_fscrypt_key,
+       [LIBCEPHFSD_OP_GET_FSCRYPT_KEY_STATUS] =
+               libcephfsd_get_fscrypt_key_status,
+       [LIBCEPHFSD_OP_LL_SET_FSCRYPT_POLICY_V2] =
+               libcephfsd_ll_set_fscrypt_policy_v2,
+       [LIBCEPHFSD_OP_LL_GET_FSCRYPT_POLICY_V2] =
+               libcephfsd_ll_get_fscrypt_policy_v2,
+       [LIBCEPHFSD_OP_LL_IS_ENCRYPTED] = libcephfsd_ll_is_encrypted,
 };
 
 static void serve_binary(proxy_client_t *client)
index 552e7dd816bf2ad1443ac9301b39053b98f8ffc7..f86cf9e5e9b1cedec3453bf468ffcdcb237713e9 100644 (file)
@@ -126,6 +126,12 @@ enum {
        LIBCEPHFSD_OP_LL_RELEASEDIR,
        LIBCEPHFSD_OP_MOUNT_PERMS,
        LIBCEPHFSD_OP_LL_NONBLOCKING_RW,
+       LIBCEPHFSD_OP_ADD_FSCRYPT_KEY,
+       LIBCEPHFSD_OP_REMOVE_FSCRYPT_KEY,
+       LIBCEPHFSD_OP_GET_FSCRYPT_KEY_STATUS,
+       LIBCEPHFSD_OP_LL_SET_FSCRYPT_POLICY_V2,
+       LIBCEPHFSD_OP_LL_GET_FSCRYPT_POLICY_V2,
+       LIBCEPHFSD_OP_LL_IS_ENCRYPTED,
 
        /* Add more operations above this comment. */
 
@@ -989,6 +995,91 @@ PROTO_CALL(ceph_ll_nonblocking_readv_writev,
        )
 );
 
+PROTO_CALL(ceph_add_fscrypt_key,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint32_t user;
+                       uint32_t kid;
+                       uint16_t key;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+               )
+       )
+);
+
+PROTO_CALL(ceph_remove_fscrypt_key,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint32_t user;
+                       uint32_t arg;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+               )
+       )
+);
+
+PROTO_CALL(ceph_get_fscrypt_key_status,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint32_t arg;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+               )
+       )
+);
+
+PROTO_CALL(ceph_ll_set_fscrypt_policy_v2,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint64_t inode;
+                       uint32_t policy;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+               )
+       )
+);
+
+PROTO_CALL(ceph_ll_get_fscrypt_policy_v2,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint64_t inode;
+                       uint32_t policy;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+               )
+       )
+);
+
+PROTO_CALL(ceph_ll_is_encrypted,
+       PROTO_REQ(
+               PROTO_VER(v0,
+                       uint64_t cmount;
+                       uint64_t inode;
+                       uint16_t tag;
+               )
+       ),
+       PROTO_ANS(
+               PROTO_VER(v0,
+                       uint32_t policy;
+               )
+       )
+);
+
 typedef union _proxy_req {
        proxy_link_req_t header;
 
@@ -1040,6 +1131,12 @@ typedef union _proxy_req {
        proxy_ceph_ll_releasedir_req_t ll_releasedir;
        proxy_ceph_mount_perms_req_t mount_perms;
        proxy_ceph_ll_nonblocking_readv_writev_req_t ll_nonblocking_rw;
+       proxy_ceph_add_fscrypt_key_req_t add_fscrypt_key;
+       proxy_ceph_remove_fscrypt_key_req_t remove_fscrypt_key;
+       proxy_ceph_get_fscrypt_key_status_req_t get_fscrypt_key_status;
+       proxy_ceph_ll_set_fscrypt_policy_v2_req_t ll_set_fscrypt_policy_v2;
+       proxy_ceph_ll_get_fscrypt_policy_v2_req_t ll_get_fscrypt_policy_v2;
+       proxy_ceph_ll_is_encrypted_req_t ll_is_encrypted;
 } proxy_req_t;
 
 PROTO_NOTIFY(ceph_ll_nonblocking_readv_writev,