]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ceph: crypto context handling for ceph
authorJeff Layton <jlayton@kernel.org>
Mon, 27 Jul 2020 14:16:09 +0000 (10:16 -0400)
committerJeff Layton <jlayton@kernel.org>
Tue, 7 Dec 2021 15:32:46 +0000 (10:32 -0500)
Have set_context do a setattr that sets the fscrypt_auth value, and
get_context just return the contents of that field.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
fs/ceph/Makefile
fs/ceph/crypto.c [new file with mode: 0644]
fs/ceph/crypto.h [new file with mode: 0644]
fs/ceph/inode.c
fs/ceph/super.c

index 50c635dc7f711c4446ac537cc44d8a08a467ba39..1f77ca04c426fdb9be333b891ebbdee504e64d30 100644 (file)
@@ -12,3 +12,4 @@ ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
 
 ceph-$(CONFIG_CEPH_FSCACHE) += cache.o
 ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o
+ceph-$(CONFIG_FS_ENCRYPTION) += crypto.o
diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
new file mode 100644 (file)
index 0000000..a513ff3
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/ceph/ceph_debug.h>
+#include <linux/xattr.h>
+#include <linux/fscrypt.h>
+
+#include "super.h"
+#include "crypto.h"
+
+static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fscrypt_auth *cfa = (struct ceph_fscrypt_auth *)ci->fscrypt_auth;
+       u32 ctxlen;
+
+       /* Non existent or too short? */
+       if (!cfa || (ci->fscrypt_auth_len < (offsetof(struct ceph_fscrypt_auth, cfa_blob) + 1)))
+               return -ENOBUFS;
+
+       /* Some format we don't recognize? */
+       if (le32_to_cpu(cfa->cfa_version) != CEPH_FSCRYPT_AUTH_VERSION)
+               return -ENOBUFS;
+
+       ctxlen = le32_to_cpu(cfa->cfa_blob_len);
+       if (len < ctxlen)
+               return -ERANGE;
+
+       memcpy(ctx, cfa->cfa_blob, ctxlen);
+       return ctxlen;
+}
+
+static int ceph_crypt_set_context(struct inode *inode, const void *ctx, size_t len, void *fs_data)
+{
+       int ret;
+       struct iattr attr = { };
+       struct ceph_iattr cia = { };
+       struct ceph_fscrypt_auth *cfa;
+
+       WARN_ON_ONCE(fs_data);
+
+       if (len > FSCRYPT_SET_CONTEXT_MAX_SIZE)
+               return -EINVAL;
+
+       cfa = kzalloc(sizeof(*cfa), GFP_KERNEL);
+       if (!cfa)
+               return -ENOMEM;
+
+       cfa->cfa_version = cpu_to_le32(CEPH_FSCRYPT_AUTH_VERSION);
+       cfa->cfa_blob_len = cpu_to_le32(len);
+       memcpy(cfa->cfa_blob, ctx, len);
+
+       cia.fscrypt_auth = cfa;
+
+       ret = __ceph_setattr(inode, &attr, &cia);
+       if (ret == 0)
+               inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED);
+       kfree(cia.fscrypt_auth);
+       return ret;
+}
+
+static bool ceph_crypt_empty_dir(struct inode *inode)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+
+       return ci->i_rsubdirs + ci->i_rfiles == 1;
+}
+
+static struct fscrypt_operations ceph_fscrypt_ops = {
+       .get_context            = ceph_crypt_get_context,
+       .set_context            = ceph_crypt_set_context,
+       .empty_dir              = ceph_crypt_empty_dir,
+};
+
+void ceph_fscrypt_set_ops(struct super_block *sb)
+{
+       fscrypt_set_ops(sb, &ceph_fscrypt_ops);
+}
diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h
new file mode 100644 (file)
index 0000000..6c3831c
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Ceph fscrypt functionality
+ */
+
+#ifndef _CEPH_CRYPTO_H
+#define _CEPH_CRYPTO_H
+
+#include <linux/fscrypt.h>
+
+struct ceph_fscrypt_auth {
+       __le32  cfa_version;
+       __le32  cfa_blob_len;
+       u8      cfa_blob[FSCRYPT_SET_CONTEXT_MAX_SIZE];
+} __packed;
+
+#ifdef CONFIG_FS_ENCRYPTION
+#define CEPH_FSCRYPT_AUTH_VERSION      1
+void ceph_fscrypt_set_ops(struct super_block *sb);
+
+#else /* CONFIG_FS_ENCRYPTION */
+
+static inline void ceph_fscrypt_set_ops(struct super_block *sb)
+{
+}
+
+#endif /* CONFIG_FS_ENCRYPTION */
+
+#endif
index bbda411019c2dfd35bda948f1fdab1ad9b164645..472873de234eb91108ca6e16bd7f2e3145d2f4f9 100644 (file)
 #include <linux/random.h>
 #include <linux/sort.h>
 #include <linux/iversion.h>
+#include <linux/fscrypt.h>
 
 #include "super.h"
 #include "mds_client.h"
 #include "cache.h"
+#include "crypto.h"
 #include <linux/ceph/decode.h>
 
 /*
@@ -636,6 +638,7 @@ void ceph_evict_inode(struct inode *inode)
        clear_inode(inode);
 
        ceph_fscache_unregister_inode_cookie(ci);
+       fscrypt_put_encryption_info(inode);
 
        __ceph_remove_caps(ci);
 
index 8d6daea351f63a85d529d34a629b68a072e393ca..93adecd86e7a5ab76eb9e735d078663bb0957c38 100644 (file)
@@ -20,6 +20,7 @@
 #include "super.h"
 #include "mds_client.h"
 #include "cache.h"
+#include "crypto.h"
 
 #include <linux/ceph/ceph_features.h>
 #include <linux/ceph/decode.h>
@@ -1110,6 +1111,8 @@ static int ceph_set_super(struct super_block *s, struct fs_context *fc)
        s->s_time_min = 0;
        s->s_time_max = U32_MAX;
 
+       ceph_fscrypt_set_ops(s);
+
        ret = set_anon_super_fc(s, fc);
        if (ret != 0)
                fsc->sb = NULL;