All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Simmons <jsimmons@infradead.org>
To: Andreas Dilger <adilger@whamcloud.com>,
	Oleg Drokin <green@whamcloud.com>, NeilBrown <neilb@suse.de>
Cc: Lustre Development List <lustre-devel@lists.lustre.org>
Subject: [lustre-devel] [PATCH 08/50] lustre: sec: make client encryption compatible with ext4
Date: Sun, 20 Mar 2022 09:30:22 -0400	[thread overview]
Message-ID: <1647783064-20688-9-git-send-email-jsimmons@infradead.org> (raw)
In-Reply-To: <1647783064-20688-1-git-send-email-jsimmons@infradead.org>

From: Sebastien Buisson <sbuisson@ddn.com>

In order to benefit from encrypted file handling implemented in
e2fsprogs, we need to adjust the way Lustre deals with encryption
context of files.

First, the encryption context needs to be stored in an xattr named
"encryption.c" instead of "security.c". But neither llite nor ldiskfs
has an xattr handler for this "encryption." xattr type. So we need
to export ldiskfs_xattr_get and ldiskfs_xattr_set_handle symbols for
this to work.

Second, we set the LDISKFS_ENCRYPT_FL flag on files for which we set
the 'encryption.c' xattr. But we just keep this flag for on-disk
inodes, and make sure the flag is cleared for in-memory inodes.
The purpose is to help e2fsprogs with encrypted files handling, while
not disturbing Lustre server side with the encryption flag (servers
are not supposed to know about it for Lustre client-side encryption).

To maintain compatibility with 2.14 in which encryption context is
stored in "security.c" xattr, we try to fetch enc context from this
xattr if getting it from "encryption.c" fails. On client side, in all
cases everything looks like encryption context is stored in
"encryption.c".

WC-bug-id: https://jira.whamcloud.com/browse/LU-13717
Lustre-commit: 4231fab66eab3e984 ("LU-13717 sec: make client encryption compatible with ext4")
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-on: https://review.whamcloud.com/45211
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
---
 fs/lustre/llite/crypto.c               | 42 ++++++++--------------
 fs/lustre/llite/llite_internal.h       | 14 +++-----
 fs/lustre/llite/xattr.c                | 65 +++++++++++++++-------------------
 include/uapi/linux/lustre/lustre_idl.h |  5 +--
 4 files changed, 50 insertions(+), 76 deletions(-)

diff --git a/fs/lustre/llite/crypto.c b/fs/lustre/llite/crypto.c
index 6a12b6c..f310d4c 100644
--- a/fs/lustre/llite/crypto.c
+++ b/fs/lustre/llite/crypto.c
@@ -31,29 +31,13 @@
 
 static int ll_get_context(struct inode *inode, void *ctx, size_t len)
 {
-	struct dentry *dentry = d_find_any_alias(inode);
-	struct lu_env *env;
-	u16 refcheck;
 	int rc;
 
-	env = cl_env_get(&refcheck);
-	if (IS_ERR(env))
-		return PTR_ERR(env);
-
-	/* Set lcc_getencctx=1 to allow this thread to read
-	 * LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr, as requested by fscrypt.
+	/* Get enc context xattr directly instead of going through the VFS,
+	 * as there is no xattr handler for "encryption.".
 	 */
-	ll_cl_add(inode, env, NULL, LCC_RW);
-	ll_env_info(env)->lti_io_ctx.lcc_getencctx = 1;
-
-	rc = __vfs_getxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
-			    ctx, len);
-
-	ll_cl_remove(inode, env);
-	cl_env_put(env, &refcheck);
-
-	if (dentry)
-		dput(dentry);
+	rc = ll_xattr_list(inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+			   XATTR_ENCRYPTION_T, ctx, len, OBD_MD_FLXATTR);
 
 	/* used as encryption unit size */
 	if (S_ISREG(inode->i_mode))
@@ -90,15 +74,15 @@ int ll_set_encflags(struct inode *inode, void *encctx, u32 encctxlen,
  *   op_data, so that it will be sent along to the server with the request that
  *   the caller is preparing, thus saving a setxattr request.
  * - inode is not NULL:
- *   normal case in which passed fs_data is a struct dentry *, letting proceed
- *   with setxattr operation.
+ *   normal case, letting proceed with setxattr operation.
  *   This use case should only be used when explicitly setting a new encryption
  *   policy on an existing, empty directory.
  */
 static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
 			  void *fs_data)
 {
-	struct dentry *dentry;
+	struct ptlrpc_request *req = NULL;
+	struct ll_sb_info *sbi;
 	int rc;
 
 	if (!inode) {
@@ -119,12 +103,16 @@ static int ll_set_context(struct inode *inode, const void *ctx, size_t len,
 	if (is_root_inode(inode))
 		return -EPERM;
 
-	dentry = (struct dentry *)fs_data;
-	set_bit(LLIF_SET_ENC_CTX, &ll_i2info(inode)->lli_flags);
-	rc = __vfs_setxattr(dentry, inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
-			    ctx, len, XATTR_CREATE);
+	sbi = ll_i2sbi(inode);
+	/* Send setxattr request to lower layers directly instead of going
+	 * through the VFS, as there is no xattr handler for "encryption.".
+	 */
+	rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
+			 OBD_MD_FLXATTR, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+			 ctx, len, XATTR_CREATE, ll_i2suppgid(inode), &req);
 	if (rc)
 		return rc;
+	ptlrpc_req_finished(req);
 
 	return ll_set_encflags(inode, (void *)ctx, len, false);
 }
diff --git a/fs/lustre/llite/llite_internal.h b/fs/lustre/llite/llite_internal.h
index dd338f2..a8d43bd 100644
--- a/fs/lustre/llite/llite_internal.h
+++ b/fs/lustre/llite/llite_internal.h
@@ -109,8 +109,6 @@ enum ll_file_flags {
 	LLIF_UPDATE_ATIME	= 4,
 	/* foreign file/dir can be unlinked unconditionnaly */
 	LLIF_FOREIGN_REMOVABLE	= 5,
-	/* setting encryption context in progress */
-	LLIF_SET_ENC_CTX	= 6,
 	/* Xattr cache is filled */
 	LLIF_XATTR_CACHE_FILLED	= 7,
 };
@@ -1285,16 +1283,11 @@ enum lcc_type {
 
 struct ll_cl_context {
 	struct list_head	 lcc_list;
-	void	   *lcc_cookie;
+	void			*lcc_cookie;
 	const struct lu_env	*lcc_env;
-	struct cl_io   *lcc_io;
-	struct cl_page *lcc_page;
+	struct cl_io		*lcc_io;
+	struct cl_page		*lcc_page;
 	enum lcc_type		 lcc_type;
-	/**
-	 * Get encryption context operation in progress,
-	 * allow getxattr of LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr
-	 */
-	unsigned int		 lcc_getencctx:1;
 };
 
 struct ll_thread_info {
@@ -1405,6 +1398,7 @@ static inline loff_t ll_file_maxbytes(struct inode *inode)
 #define XATTR_ACL_DEFAULT_T	5
 #define XATTR_LUSTRE_T		6
 #define XATTR_OTHER_T		7
+#define XATTR_ENCRYPTION_T	9
 
 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size);
 int ll_xattr_list(struct inode *inode, const char *name, int type,
diff --git a/fs/lustre/llite/xattr.c b/fs/lustre/llite/xattr.c
index ce9585a..3a342ad 100644
--- a/fs/lustre/llite/xattr.c
+++ b/fs/lustre/llite/xattr.c
@@ -132,15 +132,14 @@ static int ll_xattr_set_common(const struct xattr_handler *handler,
 			return -EPERM;
 	}
 
-	/* Setting LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr is only allowed
-	 * when defining an encryption policy on a directory, ie when it
-	 * comes from ll_set_context().
-	 * When new files/dirs are created in an encrypted dir, the xattr
-	 * is set directly in the create request.
+	/* This check is required for compatibility with 2.14, in which
+	 * encryption context is stored in security.c xattr.
+	 * Setting the encryption context should only be possible by llcrypt
+	 * when defining an encryption policy on a directory.
+	 * When new files/dirs are created in an encrypted dir, the enc
+	 * context is set directly in the create request.
 	 */
-	if (handler->flags == XATTR_SECURITY_T &&
-	    !strcmp(name, "c") &&
-	    !test_and_clear_bit(LLIF_SET_ENC_CTX, &ll_i2info(inode)->lli_flags))
+	if (handler->flags == XATTR_SECURITY_T && strcmp(name, "c") == 0)
 		return -EPERM;
 
 	fullname = kasprintf(GFP_KERNEL, "%s%s", xattr_prefix(handler), name);
@@ -364,19 +363,13 @@ int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer,
 	void *xdata;
 	int rc;
 
-	/* Getting LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr is only allowed
-	 * when it comes from ll_get_context(), ie when fscrypt needs to
-	 * know the encryption context.
-	 * Otherwise, any direct reading of this xattr returns -EPERM.
+	/* This check is required for compatibility with 2.14, in which
+	 * encryption context is stored in security.c xattr. Accessing the
+	 * encryption context should only be possible by llcrypt.
 	 */
-	if (type == XATTR_SECURITY_T &&
-	    !strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT)) {
-		struct ll_cl_context *lcc = ll_cl_find(inode);
-
-		if (!lcc || !lcc->lcc_getencctx) {
-			rc = -EPERM;
-			goto out_xattr;
-		}
+	if (type == XATTR_SECURITY_T && strcmp(name, "security.c") == 0) {
+		rc = -EPERM;
+		goto out_xattr;
 	}
 
 	if (sbi->ll_xattr_cache_enabled && type != XATTR_ACL_ACCESS_T &&
@@ -613,7 +606,6 @@ static int ll_xattr_get(const struct xattr_handler *handler,
 
 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-	struct inode *dir = d_inode(dentry->d_parent);
 	struct inode *inode = d_inode(dentry);
 	struct ll_sb_info *sbi = ll_i2sbi(inode);
 	ktime_t kstart = ktime_get();
@@ -643,38 +635,37 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 	rem = rc;
 
 	while (rem > 0) {
+		const struct xattr_handler *xh = get_xattr_type(xattr_name);
 		bool hide_xattr = false;
 
-		/* Listing xattrs should not expose
-		 * LL_XATTR_NAME_ENCRYPTION_CONTEXT xattr, unless it comes
-		 * from fscrypt.
-		 */
-		if (get_xattr_type(xattr_name)->flags == XATTR_SECURITY_T &&
-		    !strcmp(xattr_name, LL_XATTR_NAME_ENCRYPTION_CONTEXT)) {
-			struct ll_cl_context *lcc = ll_cl_find(inode);
-
-			if (!lcc || !lcc->lcc_getencctx)
-				hide_xattr = true;
-		}
-
 		/* Hide virtual project id xattr from the list when
 		 * parent has the inherit flag and the same project id,
 		 * so project id won't be messed up by copying the xattrs
 		 * when mv to a tree with different project id.
 		 */
-		if (get_xattr_type(xattr_name)->flags == XATTR_TRUSTED_T &&
+		if (xh && xh->flags == XATTR_TRUSTED_T &&
 		    strcmp(xattr_name, XATTR_NAME_PROJID) == 0) {
+			struct inode *dir = d_inode(dentry->d_parent);
+
 			if (ll_i2info(inode)->lli_projid ==
-					ll_i2info(dir)->lli_projid &&
+			    ll_i2info(dir)->lli_projid &&
 			    test_bit(LLIF_PROJECT_INHERIT,
 				     &ll_i2info(dir)->lli_flags))
 				hide_xattr = true;
+		} else if (xh && xh->flags == XATTR_SECURITY_T &&
+			   strcmp(xattr_name, "security.c") == 0) {
+			/* Listing xattrs should not expose encryption
+			 * context. There is no handler defined for
+			 * XATTR_ENCRYPTION_PREFIX, so this test is just
+			 * needed for compatibility with 2.14, in which
+			 * encryption context is stored in security.c xattr.
+			 */
+			hide_xattr = true;
 		}
 
 		len = strnlen(xattr_name, rem - 1) + 1;
 		rem -= len;
-		if (!xattr_type_filter(sbi, hide_xattr ? NULL :
-				       get_xattr_type(xattr_name))) {
+		if (!xattr_type_filter(sbi, hide_xattr ? NULL : xh)) {
 			/* Skip OK xattr type, leave it in buffer. */
 			xattr_name += len;
 			continue;
diff --git a/include/uapi/linux/lustre/lustre_idl.h b/include/uapi/linux/lustre/lustre_idl.h
index 78e20a7..753df16 100644
--- a/include/uapi/linux/lustre/lustre_idl.h
+++ b/include/uapi/linux/lustre/lustre_idl.h
@@ -1065,7 +1065,7 @@ struct lov_mds_md_v1 {		/* LOV EA mds/wire data (little-endian) */
 #define XATTR_USER_PREFIX	"user."
 #define XATTR_TRUSTED_PREFIX	"trusted."
 #define XATTR_SECURITY_PREFIX	"security."
-#define XATTR_LUSTRE_PREFIX	"lustre."
+#define XATTR_ENCRYPTION_PREFIX	"encryption."
 
 #define XATTR_NAME_SOM		"trusted.som"
 #define XATTR_NAME_LOV		"trusted.lov"
@@ -1080,7 +1080,8 @@ struct lov_mds_md_v1 {		/* LOV EA mds/wire data (little-endian) */
 #define XATTR_NAME_LFSCK_NAMESPACE "trusted.lfsck_namespace"
 #define XATTR_NAME_PROJID	"trusted.projid"
 
-#define LL_XATTR_NAME_ENCRYPTION_CONTEXT XATTR_SECURITY_PREFIX"c"
+#define LL_XATTR_NAME_ENCRYPTION_CONTEXT_OLD XATTR_SECURITY_PREFIX"c"
+#define LL_XATTR_NAME_ENCRYPTION_CONTEXT XATTR_ENCRYPTION_PREFIX"c"
 
 struct lov_mds_md_v3 {		/* LOV EA mds/wire data (little-endian) */
 	__u32 lmm_magic;	/* magic number = LOV_MAGIC_V3 */
-- 
1.8.3.1

_______________________________________________
lustre-devel mailing list
lustre-devel@lists.lustre.org
http://lists.lustre.org/listinfo.cgi/lustre-devel-lustre.org

  parent reply	other threads:[~2022-03-20 13:31 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-20 13:30 [lustre-devel] [PATCH 00/50] lustre: update to OpenSFS tree as of March 20, 2022 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 01/50] lustre: type cleanups and remove debug statements James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 02/50] lustre: osc: Fix grant test for ARM James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 03/50] lnet: extend nids in struct lnet_msg James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 04/50] lnet: Change lnet_send() to take large-addr nids James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 05/50] lnet: use large nids in struct lnet_event James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 06/50] lnet: socklnd: prepare for new KSOCK_MSG type James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 07/50] lnet: socklnd: don't deref lnet_hdr in LNDs James Simmons
2022-03-20 13:30 ` James Simmons [this message]
2022-03-20 13:30 ` [lustre-devel] [PATCH 09/50] lustre: sec: allow subdir mount of encrypted dir James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 10/50] lustre: fld: repeat rpc in fld_client_rpc after EAGAIN James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 11/50] lustre: fld: don't obtain a slot for fld request James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 12/50] lustre: update version to 2.14.57 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 13/50] lustre: llite: deadlock in ll_new_node() James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 14/50] lnet: o2iblnd: avoid static allocation for msg tx James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 15/50] lnet: separate lnet_hdr in msg from that in lnd James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 16/50] lnet: change lnet_hdr to store large nids James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 17/50] lnet: change lnet_prep_send to take net_processid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 18/50] lnet: convert to struct lnet_process_id in lib-move James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 19/50] lnet: convert LNetGetID to return an large-addr pid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 20/50] lnet: alter lnd_notify_peer_down() to take lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 21/50] lnet: socklnd: move lnet_hdr unpack into ->pro_unpack James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 22/50] lnet: socklnd: Change ksock_hello_msg to struct lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 23/50] lnet: socklnd: add hello message version 4 James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 24/50] lnet: Convert ping to support 16-bytes address James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 25/50] lnet: convert nids in lnet_parse to lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 26/50] lnet: change src_nid arg to lnet_parse() to 16byte James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 27/50] lnet: Fix NULL-deref in lnet_nidstr_r() James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 28/50] lnet: change lnet_del_route() to take lnet_nid James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 29/50] lustre: llite: Move free user pages James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 30/50] lustre: llite: Do not get/put DIO pages James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 31/50] lustre: llite: Remove unnecessary page get/put James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 32/50] lustre: llite: LL_IOC_LMV_GETSTRIPE 'default' shows inherit layout James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 33/50] lustre: hsm: update size upon completion of data version James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 34/50] lustre: llite: Delay dput in ll_dirty_page_discard_warn James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 35/50] lnet: libcfs: Use FAIL_CHECK_QUIET for fake i/o James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 36/50] lnet: Avoid peer NI recovery for local interface James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 37/50] lustre: osc: add OBD_IOC_GETATTR support for osc James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 38/50] lustre: sec: present .fscrypt in subdir mount James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 39/50] lnet: improve hash distribution across CPTs James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 40/50] lustre: osc: osc_extent_wait() deadlock James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 41/50] lustre: quota: delete unused quota ID James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 42/50] lnet: Check LNET_NID_IS_ANY in LNET_NID_NET James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 43/50] lustre: llite: clear async errors on write commit sync James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 44/50] lnet: lnet_peer_data_present() memory leak James Simmons
2022-03-20 13:30 ` [lustre-devel] [PATCH 45/50] lnet: Don't use pref NI for reserved portal James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 46/50] lnet: o2iblnd: avoid memory copy for short msg James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 47/50] lustre: llite: set default LMV hash type with 2.12 MDS James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 48/50] lnet: Stop discovery on deleted peer NI James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 49/50] lustre: sec: fix DIO for encrypted files James Simmons
2022-03-20 13:31 ` [lustre-devel] [PATCH 50/50] lustre: ptlrpc: Use after free of 'conn' in rhashtable retry James Simmons

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=1647783064-20688-9-git-send-email-jsimmons@infradead.org \
    --to=jsimmons@infradead.org \
    --cc=adilger@whamcloud.com \
    --cc=green@whamcloud.com \
    --cc=lustre-devel@lists.lustre.org \
    --cc=neilb@suse.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.