From: Jeff Layton <jlayton@kernel.org>
To: ceph-devel@vger.kernel.org
Cc: linux-fscrypt@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: [RFC PATCH v5 05/19] ceph: crypto context handling for ceph
Date: Fri, 26 Mar 2021 13:32:13 -0400 [thread overview]
Message-ID: <20210326173227.96363-6-jlayton@kernel.org> (raw)
In-Reply-To: <20210326173227.96363-1-jlayton@kernel.org>
Store the fscrypt context for an inode as an encryption.ctx xattr.
When we get a new inode in a trace, set the S_ENCRYPTED bit if
the xattr blob has an encryption.ctx xattr.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/ceph/Makefile | 1 +
fs/ceph/crypto.c | 42 ++++++++++++++++++++++++++++++++++++++++++
fs/ceph/crypto.h | 24 ++++++++++++++++++++++++
fs/ceph/inode.c | 15 +++++++++++++++
fs/ceph/super.c | 3 +++
fs/ceph/super.h | 1 +
fs/ceph/xattr.c | 32 ++++++++++++++++++++++++++++++++
7 files changed, 118 insertions(+)
create mode 100644 fs/ceph/crypto.c
create mode 100644 fs/ceph/crypto.h
diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile
index 50c635dc7f71..1f77ca04c426 100644
--- a/fs/ceph/Makefile
+++ b/fs/ceph/Makefile
@@ -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
index 000000000000..dbe8b60fd1b0
--- /dev/null
+++ b/fs/ceph/crypto.c
@@ -0,0 +1,42 @@
+// 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)
+{
+ return __ceph_getxattr(inode, CEPH_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
+}
+
+static int ceph_crypt_set_context(struct inode *inode, const void *ctx, size_t len, void *fs_data)
+{
+ int ret;
+
+ WARN_ON_ONCE(fs_data);
+ ret = __ceph_setxattr(inode, CEPH_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len, XATTR_CREATE);
+ if (ret == 0)
+ inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED);
+ 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,
+ .max_namelen = NAME_MAX,
+};
+
+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
index 000000000000..189bd8424284
--- /dev/null
+++ b/fs/ceph/crypto.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Ceph fscrypt functionality
+ */
+
+#ifndef _CEPH_CRYPTO_H
+#define _CEPH_CRYPTO_H
+
+#include <linux/fscrypt.h>
+
+#define CEPH_XATTR_NAME_ENCRYPTION_CONTEXT "encryption.ctx"
+
+#ifdef CONFIG_FS_ENCRYPTION
+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
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 2c512475c170..33dda23c99e0 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -14,10 +14,12 @@
#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>
/*
@@ -566,6 +568,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);
@@ -944,6 +947,18 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
ceph_forget_all_cached_acls(inode);
ceph_security_invalidate_secctx(inode);
xattr_blob = NULL;
+
+ /*
+ * Most inodes inherit the encrypted flag from their parent,
+ * but empty directories can end up being encrypted later via
+ * ioctl. Only check for encryption if it's not already encrypted,
+ * and it's a new inode, or a directory.
+ */
+ if (!IS_ENCRYPTED(inode) &&
+ ((inode->i_state & I_NEW) || S_ISDIR(inode->i_mode))) {
+ if (ceph_inode_has_xattr(ci, CEPH_XATTR_NAME_ENCRYPTION_CONTEXT))
+ inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED);
+ }
}
/* finally update i_version */
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 9b1b7f4cfdd4..cdac6ff675e2 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -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>
@@ -988,6 +989,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;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 5e0e1aeee1b5..36b12e33b2bc 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1016,6 +1016,7 @@ extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
extern struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci);
extern void __ceph_destroy_xattrs(struct ceph_inode_info *ci);
extern const struct xattr_handler *ceph_xattr_handlers[];
+bool ceph_inode_has_xattr(struct ceph_inode_info *ci, const char *name);
struct ceph_acl_sec_ctx {
#ifdef CONFIG_CEPH_FS_POSIX_ACL
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 02f59bcb4f27..38ac2968e4a1 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -1360,6 +1360,38 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
ceph_pagelist_release(as_ctx->pagelist);
}
+/* Return true if inode's xattr blob has an xattr named "name" */
+bool ceph_inode_has_xattr(struct ceph_inode_info *ci, const char *name)
+{
+ void *p, *end;
+ u32 numattr;
+ size_t namelen;
+
+ lockdep_assert_held(&ci->i_ceph_lock);
+
+ if (!ci->i_xattrs.blob || ci->i_xattrs.blob->vec.iov_len <= 4)
+ return false;
+
+ namelen = strlen(name);
+ p = ci->i_xattrs.blob->vec.iov_base;
+ end = p + ci->i_xattrs.blob->vec.iov_len;
+ ceph_decode_32_safe(&p, end, numattr, bad);
+
+ while (numattr--) {
+ u32 len;
+
+ ceph_decode_32_safe(&p, end, len, bad);
+ ceph_decode_need(&p, end, len, bad);
+ if (len == namelen && !memcmp(p, name, len))
+ return true;
+ p += len;
+ ceph_decode_32_safe(&p, end, len, bad);
+ ceph_decode_skip_n(&p, end, len, bad);
+ }
+bad:
+ return false;
+}
+
/*
* List of handlers for synthetic system.* attributes. Other
* attributes are handled directly.
--
2.30.2
next prev parent reply other threads:[~2021-03-26 17:33 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-26 17:32 [RFC PATCH v5 00/19] ceph+fscrypt: context, filename and symlink support Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 01/19] vfs: export new_inode_pseudo Jeff Layton
2021-04-08 1:08 ` Eric Biggers
2021-04-08 16:18 ` Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 02/19] fscrypt: export fscrypt_base64_encode and fscrypt_base64_decode Jeff Layton
2021-04-08 1:06 ` Eric Biggers
2021-04-08 16:22 ` Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 03/19] fscrypt: export fscrypt_fname_encrypt and fscrypt_fname_encrypted_size Jeff Layton
2021-04-08 1:19 ` Eric Biggers
2021-03-26 17:32 ` [RFC PATCH v5 04/19] fscrypt: add fscrypt_context_for_new_inode Jeff Layton
2021-04-08 1:21 ` Eric Biggers
2021-04-08 16:27 ` Jeff Layton
2021-03-26 17:32 ` Jeff Layton [this message]
2021-03-26 17:32 ` [RFC PATCH v5 06/19] ceph: implement -o test_dummy_encryption mount option Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 07/19] ceph: preallocate inode for ops that may create one Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 08/19] ceph: add routine to create fscrypt context prior to RPC Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 09/19] ceph: make ceph_msdc_build_path use ref-walk Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 10/19] ceph: add encrypted fname handling to ceph_mdsc_build_path Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 11/19] ceph: decode alternate_name in lease info Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 12/19] ceph: send altname in MClientRequest Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 13/19] ceph: properly set DCACHE_NOKEY_NAME flag in lookup Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 14/19] ceph: make d_revalidate call fscrypt revalidator for encrypted dentries Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 15/19] ceph: add helpers for converting names for userland presentation Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 16/19] ceph: add fscrypt support to ceph_fill_trace Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 17/19] ceph: add support to readdir for encrypted filenames Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 18/19] ceph: create symlinks with encrypted and base64-encoded targets Jeff Layton
2021-03-26 17:32 ` [RFC PATCH v5 19/19] ceph: add fscrypt ioctls Jeff Layton
2021-04-06 15:38 ` Luis Henriques
2021-04-06 16:03 ` Jeff Layton
2021-04-06 16:24 ` Luis Henriques
2021-04-06 17:27 ` Jeff Layton
2021-04-06 18:04 ` Luis Henriques
2021-04-07 12:47 ` Jeff Layton
2021-03-26 18:38 ` [RFC PATCH v5 00/19] ceph+fscrypt: context, filename and symlink support Jeff Layton
2021-03-31 20:35 ` [RFC PATCH v5 20/19] ceph: make ceph_get_name decrypt filenames Jeff Layton
2021-04-01 11:14 ` Luis Henriques
2021-04-01 12:15 ` Jeff Layton
2021-04-01 13:05 ` Luis Henriques
2021-04-01 13:12 ` Jeff Layton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210326173227.96363-6-jlayton@kernel.org \
--to=jlayton@kernel.org \
--cc=ceph-devel@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).