Whamcloud - gitweb
LU-15420 sec: handle simple fscrypt changes for 5.15 kernels 25/49125/22
authorJames Simmons <jsimmons@infradead.org>
Wed, 8 Feb 2023 13:04:45 +0000 (08:04 -0500)
committerOleg Drokin <green@whamcloud.com>
Fri, 17 Feb 2023 02:25:24 +0000 (02:25 +0000)
The patch covers the low impact changes to the Linux kernels
fscrypt API. The changes are:

For Linux kernel version 5.9-rc4 the following commits are:

8b10fe68985278de4926daa56ad6af701839e40a removed the inode
parameter for the fscrypt function fscrypt_fname_alloc_buffer()

5b2a828b98ec1872799b1b4d82113c76a12d594f ended up exporting
fscrypt_d_revalidate() and stopped stomping on the d_ops.

c8c868abc91ff23f6f5c4444c419de7c277d77e1 changed
fscrypt_set_test_dummy_encryption() take a 'const char *

ac4acb1f4b2b6b7e8d913537cccec8789903e164 moved the fscrypt core
from using fscrypt_context to using fscrypt_policy that is user
forward facing.

Lastly for Linux kernel version 5.10-rc4 the commit

ec0caa974cd092549ab282deb8ec7ea73b36eba0 stopped exporting
fscrypt_get_encryption_info(). Use fscrypt_prepare_readdir()
in its place.

70fb2612aab62d47e03f82eaa7384a8d30ca175d renamed a field in
struct fscrypt_name. Since Lustre can't use fscrypt_prepare_lookup
we have to deal with this change.

Remove sptlrpc_enc_pool_del_user() since its an empty function
that waste cycles calling it.

The other large change was the replacement of
fscrypt_inherit_context which is described in Linux commit
a992b20cd4ee360dbbe6f69339cb07146e4304d6. This change is very
large since it expects the target inode to be available. Lustre
uses fscrypt_inherit_context before the inode is available so
this is a much more complex change that will be done in another
patch.

de3cdc6e75179a2324c23400b21483a1372c95e1 makes fscrypt_require_key
private. You need to test the key's presence with
fscrypt_has_encryption_key() instead but that key needs to be
setup first by the new function fscrypt_prepare_new_inode().
Since this is the case we wait to introduce this change.

Change-Id: I4bed7fef6e3302c0258c0f1563f4e180258d7a5a
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49125
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
14 files changed:
lustre/autoconf/lustre-core.m4
lustre/include/lustre_crypto.h
lustre/include/lustre_disk.h
lustre/include/lustre_sec.h
lustre/llite/crypto.c
lustre/llite/dcache.c
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/lproc_llite.c
lustre/llite/namei.c
lustre/ptlrpc/gss/sec_gss.c
lustre/ptlrpc/sec_bulk.c

index 0f73072..c7c4d4b 100644 (file)
@@ -2877,6 +2877,128 @@ AC_DEFUN([LC_FSCRYPT_DUMMY_CONTEXT_ENABLED], [
 ]) # LC_FSCRYPT_DUMMY_CONTEXT_ENABLED
 
 #
+# LC_FSCRYPT_FNAME_ALLOC_BUFFER
+#
+# Kernel 5.9-rc4 8b10fe68985278de4926daa56ad6af701839e40a
+# removed the inode parameter for the fscrypt function
+# fscrypt_fname_alloc_buffer()
+#
+AC_DEFUN([LC_FSCRYPT_FNAME_ALLOC_BUFFER], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if fscrypt_fname_alloc_buffer() removed inode parameter],
+fscrypt_fname_alloc_buffer, [
+       #include <linux/fscrypt.h>
+],[
+       fscrypt_fname_alloc_buffer(0, NULL);
+],[
+       AC_DEFINE(HAVE_FSCRYPT_FNAME_ALLOC_BUFFER_NO_INODE, 1,
+               [fscrypt_fname_alloc_buffer() doesn't use inode parameter])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_FSCRYPT_FNAME_ALLOC_BUFFER
+
+#
+# LC_FSCRYPT_SET_CONTEXT
+#
+# Kernel 5.9-rc4 a992b20cd4ee360dbbe6f69339cb07146e4304d6
+# fscrypt_get_encryption_info() is not GFP_NOFS safe which
+# is used by fscrypt_inherit_context. Replace fscrypt_inherit_context,
+# with two new functions, fscrypt_prepare_new_inode() and
+# fscrypt_set_context()
+#
+AC_DEFUN([LC_FSCRYPT_SET_CONTEXT], [
+LB_CHECK_COMPILE([if 'fscrypt_set_context()' exist],
+fscrypt_set_context, [
+       #include <linux/fscrypt.h>
+],[
+       fscrypt_set_context(NULL, NULL);
+       fscrypt_prepare_new_inode(NULL, NULL, NULL);
+],[
+       AC_DEFINE(HAVE_FSCRYPT_SET_CONTEXT, 1,
+               [fscrypt_set_context() does exist])
+])
+]) # LC_FSCRYPT_SET_CONTEXT
+
+#
+# LC_FSCRYPT_D_REVALIDATE
+#
+# kernel 5.9-rc4 5b2a828b98ec1872799b1b4d82113c76a12d594f
+# exported fscrypt_d_revalidate()
+#
+AC_DEFUN([LC_FSCRYPT_D_REVALIDATE], [
+LB_CHECK_EXPORT([fscrypt_d_revalidate], [fs/crypto/fname.c],
+       [AC_DEFINE(HAVE_FSCRYPT_D_REVALIDATE, 1,
+                  [fscrypt_d_revalidate() is exported by the kernel])])
+]) # LC_FSCRYPT_D_REVALIDATE
+
+#
+# LC_FSCRYPT_NOKEY_NAME
+#
+# kernel 5.9-rc4 70fb2612aab62d47e03f82eaa7384a8d30ca175d
+# renamed is_ciphertext_name to is_nokey_name
+#
+AC_DEFUN([LC_FSCRYPT_NOKEY_NAME], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if struct fscrypt_name has is_nokey_name field],
+fname_is_nokey_name, [
+       #include <linux/fscrypt.h>
+],[
+       struct fscrypt_name fname;
+
+       fname.is_nokey_name = true;
+],[
+       AC_DEFINE(HAVE_FSCRYPT_NOKEY_NAME, 1,
+               [struct fscrypt_name has is_nokey_name field])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_FSCRYPT_NOKEY_NAME
+
+#
+# LC_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG
+# Kernel 5.9-rc4 c8c868abc91ff23f6f5c4444c419de7c277d77e1
+# changed fscrypt_set_test_dummy_encryption() take a 'const char *
+#
+AC_DEFUN([LC_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if fscrypt_set_test_dummy_encryption() take 'const char' parameter],
+fscrypt_set_test_dummy_encryption, [
+       #include <linux/fscrypt.h>
+],[
+       char *arg = "arg";
+       fscrypt_set_test_dummy_encryption(NULL, arg, NULL);
+],[
+       AC_DEFINE(HAVE_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG, 1,
+               [fscrypt_set_test_dummy_encryption() take 'const char' parameter])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG
+
+#
+# LC_FSCRYPT_DUMMY_POLICY
+#
+# Kernel 5.9-rc4 ac4acb1f4b2b6b7e8d913537cccec8789903e164
+# move the test dummy context for fscrypt_policy which is
+# also used by the user land interface.
+#
+AC_DEFUN([LC_FSCRYPT_DUMMY_POLICY], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if fscrypt_free_dummy_policy() exists],
+fscrypt_free_dummy_policy, [
+       #include <linux/fscrypt.h>
+],[
+       fscrypt_free_dummy_policy(NULL);
+],[
+       AC_DEFINE(HAVE_FSCRYPT_DUMMY_POLICY, 1,
+               [fscrypt_free_dummy_policy() exists])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_FSCRYPT_DUMMY_POLICY
+
+#
 # LC_HAVE_ITER_FILE_SPLICE_WRITE
 #
 # Linux commit v5.9-rc1-6-g36e2c7421f02
@@ -2923,6 +3045,28 @@ AC_DEFUN([LC_FSCRYPT_IS_NOKEY_NAME], [
 ]) # LC_FSCRYPT_IS_NOKEY_NAME
 
 #
+# LC_FSCRYPT_PREPARE_READDIR
+#
+# Kernel 5.10-rc4 ec0caa974cd092549ab282deb8ec7ea73b36eba0
+# replaced fscrypt_get_encryption_info() with
+# fscrypt_prepare_readdir()
+#
+AC_DEFUN([LC_FSCRYPT_PREPARE_READDIR], [
+tmp_flags="$EXTRA_KCFLAGS"
+EXTRA_KCFLAGS="-Werror"
+LB_CHECK_COMPILE([if fscrypt_prepare_readdir() exists],
+fscrypt_prepare_readdir, [
+       #include <linux/fscrypt.h>
+],[
+       fscrypt_prepare_readdir(NULL);
+],[
+       AC_DEFINE(HAVE_FSCRYPT_PREPARE_READDIR, 1,
+               [fscrypt_prepare_readdir() exists])
+])
+EXTRA_KCFLAGS="$tmp_flags"
+]) # LC_FSCRYPT_PREPARE_READDIR
+
+#
 # LC_BIO_SET_DEV
 #
 # Linux: v5.11-rc5-9-g309dca309fc3
@@ -3558,8 +3702,17 @@ AC_DEFUN([LC_PROG_LINUX_RESULTS], [
        # 5.9
        LC_HAVE_ITER_FILE_SPLICE_WRITE
 
+       # 5.9
+       LC_FSCRYPT_FNAME_ALLOC_BUFFER
+       LC_FSCRYPT_SET_CONTEXT
+       LC_FSCRYPT_D_REVALIDATE
+       LC_FSCRYPT_NOKEY_NAME
+       LC_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG
+       LC_FSCRYPT_DUMMY_POLICY
+
        # 5.10
        LC_FSCRYPT_IS_NOKEY_NAME
+       LC_FSCRYPT_PREPARE_READDIR
 
        # 5.11
        LC_BIO_SET_DEV
index d048470..4eca297 100644 (file)
 #define __FS_HAS_ENCRYPTION 1
 #include <linux/fscrypt.h>
 
+/* LLCRYPT_DIGESTED_* is provided by llcrypt.h but that is not present
+ * for native fscrypt builds
+ */
+#define LLCRYPT_DIGESTED_CHAR          '+'
+#define LLCRYPT_DIGESTED_CHAR_OLD      '_'
 #define LL_CRYPTO_BLOCK_SIZE           FS_CRYPTO_BLOCK_SIZE
 #define llcrypt_name                   fscrypt_name
 #define llcrypt_str                    fscrypt_str
 #define llcrypt_init()                 0
 #define llcrypt_exit()                 {}
 #ifndef HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED
-#define llcrypt_context                        fscrypt_context
-#define llcrypt_dummy_context          fscrypt_dummy_context
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+#define llcrypt_policy                 fscrypt_policy
+#define llcrypt_dummy_policy           fscrypt_dummy_policy
+#else
+#define llcrypt_policy                 fscrypt_context
+#define llcrypt_dummy_policy           fscrypt_dummy_context
+#endif
+#endif
+#ifdef HAVE_FSCRYPT_D_REVALIDATE
+#define llcrypt_d_revalidate(dentry, flags)                            \
+       fscrypt_d_revalidate(dentry, flags)
+#else
+       int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
 #endif
-#define llcrypt_require_key(inode)     \
+#define llcrypt_require_key(inode)     \
        fscrypt_require_key(inode)
 #define llcrypt_has_encryption_key(inode) fscrypt_has_encryption_key(inode)
 #define llcrypt_encrypt_pagecache_blocks(page, len, offs, gfp_flags)   \
        fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num)
 #define llcrypt_inherit_context(parent, child, fs_data, preload)       \
        fscrypt_inherit_context(parent, child, fs_data, preload)
-#define llcrypt_get_encryption_info(inode) fscrypt_get_encryption_info(inode)
+#ifdef HAVE_FSCRYPT_PREPARE_READDIR
+#define llcrypt_prepare_readdir(inode) fscrypt_prepare_readdir(inode)
+#else
+#define llcrypt_prepare_readdir(inode) fscrypt_get_encryption_info(inode)
+#endif
 #define llcrypt_put_encryption_info(inode) fscrypt_put_encryption_info(inode)
 #define llcrypt_free_inode(inode)         fscrypt_free_inode(inode)
 #define llcrypt_finalize_bounce_page(pagep)  fscrypt_finalize_bounce_page(pagep)
        __fscrypt_prepare_lookup(inode, dentry, fname)
 #define llcrypt_set_ops(sb, cop)       fscrypt_set_ops(sb, cop)
 #define llcrypt_sb_free(sb)            {}
+#ifdef HAVE_FSCRYPT_FNAME_ALLOC_BUFFER_NO_INODE
+#define llcrypt_fname_alloc_buffer(inode, max_encrypted_len, crypto_str) \
+       fscrypt_fname_alloc_buffer(max_encrypted_len, crypto_str)
+#else
 #define llcrypt_fname_alloc_buffer(inode, max_encrypted_len, crypto_str) \
        fscrypt_fname_alloc_buffer(inode, max_encrypted_len, crypto_str)
+#endif
 #define llcrypt_fname_disk_to_usr(inode, hash, minor_hash, iname, oname) \
        fscrypt_fname_disk_to_usr(inode, hash, minor_hash, iname, oname)
 #define llcrypt_fname_free_buffer(crypto_str) \
 
 #else /* HAVE_LUSTRE_CRYPTO && !CONFIG_LL_ENCRYPTION */
 #include <libcfs/crypto/llcrypt.h>
+
+#define llcrypt_prepare_readdir(inode) llcrypt_get_encryption_info(inode)
+
+int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
+
 #endif /* !HAVE_LUSTRE_CRYPTO || CONFIG_LL_ENCRYPTION */
 
+#if !defined(HAVE_FSCRYPT_IS_NOKEY_NAME) || defined(CONFIG_LL_ENCRYPTION)
+
 #ifndef DCACHE_NOKEY_NAME
 #define DCACHE_NOKEY_NAME               0x02000000 /* Enc name without key */
 #endif
 
-#if !defined(HAVE_FSCRYPT_IS_NOKEY_NAME) || defined(CONFIG_LL_ENCRYPTION)
-
 static inline bool llcrypt_is_nokey_name(const struct dentry *dentry)
 {
        return dentry->d_flags & DCACHE_NOKEY_NAME;
@@ -137,11 +167,16 @@ static inline bool llcrypt_is_nokey_name(const struct dentry *dentry)
        fscrypt_show_test_dummy_encryption(seq, sep, sb)
 #define llcrypt_set_test_dummy_encryption(sb, arg, ctx)                \
        fscrypt_set_test_dummy_encryption(sb, arg, ctx)
-#define llcrypt_free_dummy_context(ctx)                                \
-       fscrypt_free_dummy_context(ctx)
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+#define llcrypt_free_dummy_policy(policy)                      \
+       fscrypt_free_dummy_policy(policy)
+#else
+#define llcrypt_free_dummy_policy(policy)                      \
+       fscrypt_free_dummy_context(policy)
+#endif
 #else
 #define llcrypt_show_test_dummy_encryption(seq, sep, sb)       {}
-#define llcrypt_free_dummy_context(ctx)                                {}
+#define llcrypt_free_dummy_policy(policy)                      {}
 #endif
 
 /* Macro to extract digest from Lustre specific structures */
index e73ce1f..544cec2 100644 (file)
@@ -159,8 +159,8 @@ struct lustre_sb_info {
        const struct llcrypt_operations *lsi_cop;
        struct key               *lsi_master_keys; /* master crypto keys used */
 #elif defined(HAVE_LUSTRE_CRYPTO) && !defined(HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED)
-       /* Encryption context for '-o test_dummy_encryption' */
-       struct llcrypt_dummy_context lsi_dummy_enc_ctx;
+       /* Dummy Encryption policy for '-o test_dummy_encryption' */
+       struct llcrypt_dummy_policy     lsi_dummy_enc_policy;
 #endif
 };
 
@@ -168,7 +168,9 @@ struct lustre_sb_info {
 #ifndef HAVE_SUPER_SETUP_BDI_NAME
 #define LSI_BDI_INITIALIZED             0x00400000
 #endif
+#ifdef CONFIG_LL_ENCRYPTION
 #define LSI_FILENAME_ENC                0x00800000 /* enable name encryption */
+#endif
 #define LSI_FILENAME_ENC_B64_OLD_CLI    0x01000000 /* use old style base64 */
 
 #define     s2lsi(sb)        ((struct lustre_sb_info *)((sb)->s_fs_info))
index 831d351..0db5e65 100644 (file)
@@ -1163,7 +1163,6 @@ int sptlrpc_cli_install_rvs_ctx(struct obd_import *imp,
 
 /* bulk security api */
 int sptlrpc_enc_pool_add_user(void);
-int sptlrpc_enc_pool_del_user(void);
 int  sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc);
 int sptlrpc_enc_pool_get_pages_array(struct page **pa, unsigned int count);
 void sptlrpc_enc_pool_put_pages(struct ptlrpc_bulk_desc *desc);
index 37a2153..d93f22c 100644 (file)
@@ -66,7 +66,7 @@ int ll_set_encflags(struct inode *inode, void *encctx, __u32 encctxlen,
        if (rc)
                return rc;
 
-       return preload ? llcrypt_get_encryption_info(inode) : 0;
+       return preload ? llcrypt_prepare_readdir(inode) : 0;
 }
 
 /* ll_set_context has 2 distinct behaviors, depending on the value of inode
@@ -168,17 +168,21 @@ static bool ll_dummy_context(struct inode *inode)
        return ll_sb_has_test_dummy_encryption(inode->i_sb);
 }
 #else
-static const union llcrypt_context *
-ll_get_dummy_context(struct super_block *sb)
+static const union llcrypt_policy *
+ll_get_dummy_policy(struct super_block *sb)
 {
        struct lustre_sb_info *lsi = s2lsi(sb);
 
-       return lsi ? lsi->lsi_dummy_enc_ctx.ctx : NULL;
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+       return lsi ? lsi->lsi_dummy_enc_policy.policy : NULL;
+#else
+       return lsi ? lsi->lsi_dummy_enc_policy.ctx : NULL;
+#endif
 }
 
 bool ll_sb_has_test_dummy_encryption(struct super_block *sb)
 {
-       return ll_get_dummy_context(sb) != NULL;
+       return ll_get_dummy_policy(sb) != NULL;
 }
 #endif
 
@@ -222,6 +226,157 @@ static bool ll_empty_dir(struct inode *inode)
        return true;
 }
 
+static int ll_digest_long_name(struct inode *dir, struct llcrypt_name *fname,
+                              struct lu_fid *fid, int digested)
+{
+       int rc = 0;
+
+       if (digested) {
+               /* Without the key, for long names user should have struct
+                * ll_digest_filename representation of the dentry instead of
+                * the name. So make sure it is valid, return fid and put
+                * excerpt of cipher text name in disk_name.
+                */
+               struct ll_digest_filename *digest;
+
+               if (fname->crypto_buf.len < sizeof(struct ll_digest_filename)) {
+                       rc = -EINVAL;
+                       goto out_free;
+               }
+               digest = (struct ll_digest_filename *)fname->disk_name.name;
+               *fid = digest->ldf_fid;
+               if (!fid_is_sane(fid)) {
+                       rc = -EINVAL;
+                       goto out_free;
+               }
+               fname->disk_name.name = digest->ldf_excerpt;
+               fname->disk_name.len = sizeof(digest->ldf_excerpt);
+       }
+       if (IS_ENCRYPTED(dir) &&
+           !name_is_dot_or_dotdot(fname->disk_name.name,
+                                  fname->disk_name.len)) {
+               int presented_len = critical_chars(fname->disk_name.name,
+                                                  fname->disk_name.len);
+               char *buf;
+
+               buf = kmalloc(presented_len + 1, GFP_NOFS);
+               if (!buf) {
+                       rc = -ENOMEM;
+                       goto out_free;
+               }
+
+               if (presented_len == fname->disk_name.len)
+                       memcpy(buf, fname->disk_name.name, presented_len);
+               else
+                       critical_encode(fname->disk_name.name,
+                                       fname->disk_name.len, buf);
+               buf[presented_len] = '\0';
+               kfree(fname->crypto_buf.name);
+               fname->crypto_buf.name = buf;
+               fname->crypto_buf.len = presented_len;
+               fname->disk_name.name = fname->crypto_buf.name;
+               fname->disk_name.len = fname->crypto_buf.len;
+       }
+out_free:
+       if (rc < 0)
+               llcrypt_free_filename(fname);
+
+       return rc;
+}
+
+/**
+ * ll_prepare_lookup() - overlay to llcrypt_prepare_lookup
+ * @dir: the directory that will be searched
+ * @de: the dentry contain the user-provided filename being searched for
+ * @fname: the filename information to be filled in
+ * @fid: fid retrieved from user-provided filename
+ *
+ * This overlay function is necessary to properly encode @fname after
+ * encryption, as it will be sent over the wire.
+ * This overlay function is also necessary to handle the case of operations
+ * carried out without the key. Normally llcrypt makes use of digested names in
+ * that case. Having a digested name works for local file systems that can call
+ * llcrypt_match_name(), but Lustre server side is not aware of encryption.
+ * FID and name hash can then easily be extracted and put into the
+ * requests sent to servers.
+ */
+int ll_prepare_lookup(struct inode *dir, struct dentry *de,
+                     struct llcrypt_name *fname, struct lu_fid *fid)
+{
+       struct qstr iname = QSTR_INIT(de->d_name.name, de->d_name.len);
+       int digested = 0;
+       int rc;
+
+       if (fid && IS_ENCRYPTED(dir) && llcrypt_policy_has_filename_enc(dir) &&
+           !llcrypt_has_encryption_key(dir)) {
+               struct lustre_sb_info *lsi = s2lsi(dir->i_sb);
+
+               if ((!(lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname.name[0] == LLCRYPT_DIGESTED_CHAR) ||
+                   ((lsi->lsi_flags & LSI_FILENAME_ENC_B64_OLD_CLI) &&
+                    iname.name[0] == LLCRYPT_DIGESTED_CHAR_OLD))
+                       digested = 1;
+       }
+
+       iname.name += digested;
+       iname.len -= digested;
+
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+       if (unlikely(filename_is_volatile(iname.name,
+                                         iname.len, NULL))) {
+               /* keep volatile name as-is, matters for server side */
+               memset(fname, 0, sizeof(struct llcrypt_name));
+               fname->disk_name.name = (unsigned char *)iname.name;
+               fname->disk_name.len = iname.len;
+               rc = 0;
+       } else {
+                /* We should use ll_prepare_lookup() but Lustre handles the
+                 * digested form its own way, incompatible with llcrypt's
+                 * digested form.
+                 */
+               rc = llcrypt_setup_filename(dir, &iname, 1, fname);
+               if ((rc == 0 || rc == -ENOENT) &&
+#if defined(HAVE_FSCRYPT_NOKEY_NAME) && !defined(CONFIG_LL_ENCRYPTION)
+                   fname->is_nokey_name) {
+#else
+                   fname->is_ciphertext_name) {
+#endif
+                       spin_lock(&de->d_lock);
+                       de->d_flags |= DCACHE_NOKEY_NAME;
+                       spin_unlock(&de->d_lock);
+               }
+       }
+       if (rc == -ENOENT) {
+               if (((is_root_inode(dir) &&
+                    iname.len == strlen(dot_fscrypt_name) &&
+                    strncmp(iname.name, dot_fscrypt_name, iname.len) == 0) ||
+                    (!llcrypt_has_encryption_key(dir) &&
+                     unlikely(filename_is_volatile(iname.name,
+                                                   iname.len, NULL))))) {
+                       /* In case of subdir mount of an encrypted directory,
+                        * we allow lookup of /.fscrypt directory.
+                        */
+                       /* For purpose of migration or mirroring without enc key
+                        * we allow lookup of volatile file without enc context.
+                        */
+                       memset(fname, 0, sizeof(struct llcrypt_name));
+                       fname->disk_name.name = (unsigned char *)iname.name;
+                       fname->disk_name.len = iname.len;
+                       rc = 0;
+               } else if (!llcrypt_has_encryption_key(dir)) {
+                       rc = -ENOKEY;
+               }
+       }
+       if (rc)
+               return rc;
+
+       return ll_digest_long_name(dir, fname, fid, digested);
+}
+
 /**
  * ll_setup_filename() - overlay to llcrypt_setup_filename
  * @dir: the directory that will be searched
@@ -304,58 +459,7 @@ int ll_setup_filename(struct inode *dir, const struct qstr *iname,
        if (rc)
                return rc;
 
-       if (digested) {
-               /* Without the key, for long names user should have struct
-                * ll_digest_filename representation of the dentry instead of
-                * the name. So make sure it is valid, return fid and put
-                * excerpt of cipher text name in disk_name.
-                */
-               struct ll_digest_filename *digest;
-
-               if (fname->crypto_buf.len < sizeof(struct ll_digest_filename)) {
-                       rc = -EINVAL;
-                       goto out_free;
-               }
-               digest = (struct ll_digest_filename *)fname->disk_name.name;
-               *fid = digest->ldf_fid;
-               if (!fid_is_sane(fid)) {
-                       rc = -EINVAL;
-                       goto out_free;
-               }
-               fname->disk_name.name = digest->ldf_excerpt;
-               fname->disk_name.len = sizeof(digest->ldf_excerpt);
-       }
-       if (IS_ENCRYPTED(dir) &&
-           !name_is_dot_or_dotdot(fname->disk_name.name,
-                                  fname->disk_name.len)) {
-               int presented_len = critical_chars(fname->disk_name.name,
-                                                  fname->disk_name.len);
-               char *buf;
-
-               buf = kmalloc(presented_len + 1, GFP_NOFS);
-               if (!buf) {
-                       rc = -ENOMEM;
-                       goto out_free;
-               }
-
-               if (presented_len == fname->disk_name.len)
-                       memcpy(buf, fname->disk_name.name, presented_len);
-               else
-                       critical_encode(fname->disk_name.name,
-                                       fname->disk_name.len, buf);
-               buf[presented_len] = '\0';
-               kfree(fname->crypto_buf.name);
-               fname->crypto_buf.name = buf;
-               fname->crypto_buf.len = presented_len;
-               fname->disk_name.name = fname->crypto_buf.name;
-               fname->disk_name.len = fname->crypto_buf.len;
-       }
-
-       return rc;
-
-out_free:
-       llcrypt_free_filename(fname);
-       return rc;
+       return ll_digest_long_name(dir, fname, fid, digested);
 }
 
 /**
@@ -446,12 +550,13 @@ int ll_fname_disk_to_usr(struct inode *inode,
        return rc;
 }
 
+#if !defined(HAVE_FSCRYPT_D_REVALIDATE) || defined(CONFIG_LL_ENCRYPTION)
 /* Copied from llcrypt_d_revalidate, as it is not exported */
 /*
  * Validate dentries in encrypted directories to make sure we aren't potentially
  * caching stale dentries after a key has been added.
  */
-int ll_revalidate_d_crypto(struct dentry *dentry, unsigned int flags)
+int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *dir;
        int err;
@@ -481,7 +586,7 @@ int ll_revalidate_d_crypto(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        dir = dget_parent(dentry);
-       err = llcrypt_get_encryption_info(d_inode(dir));
+       err = llcrypt_prepare_readdir(d_inode(dir));
        valid = !llcrypt_has_encryption_key(d_inode(dir));
        dput(dir);
 
@@ -490,6 +595,7 @@ int ll_revalidate_d_crypto(struct dentry *dentry, unsigned int flags)
 
        return valid;
 }
+#endif /* !HAVE_FSCRYPT_D_REVALIDATE || CONFIG_LL_ENCRYPTION */
 
 const struct llcrypt_operations lustre_cryptops = {
        .key_prefix             = "lustre:",
@@ -498,8 +604,12 @@ const struct llcrypt_operations lustre_cryptops = {
 #ifdef HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED
        .dummy_context          = ll_dummy_context,
 #else
-       .get_dummy_context      = ll_get_dummy_context,
+#ifdef HAVE_FSCRYPT_DUMMY_POLICY
+       .get_dummy_policy       = ll_get_dummy_policy,
+#else
+       .get_dummy_context      = ll_get_dummy_policy,
 #endif
+#endif /* !HAVE_FSCRYPT_DUMMY_CONTEXT_ENABLED */
        .empty_dir              = ll_empty_dir,
        .max_namelen            = NAME_MAX,
 };
@@ -542,6 +652,20 @@ void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set)
 {
 }
 
+int ll_prepare_lookup(struct inode *dir, struct dentry *de,
+                     struct llcrypt_name *fname, struct lu_fid *fid)
+{
+       const struct qstr *iname = &de->d_name;
+
+       if (fid) {
+               fid->f_seq = 0;
+               fid->f_oid = 0;
+               fid->f_ver = 0;
+       }
+
+       return llcrypt_setup_filename(dir, iname, 1, fname);
+}
+
 int ll_setup_filename(struct inode *dir, const struct qstr *iname,
                      int lookup, struct llcrypt_name *fname,
                      struct lu_fid *fid)
@@ -563,7 +687,7 @@ int ll_fname_disk_to_usr(struct inode *inode,
        return llcrypt_fname_disk_to_usr(inode, hash, minor_hash, iname, oname);
 }
 
-int ll_revalidate_d_crypto(struct dentry *dentry, unsigned int flags)
+int llcrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        return 1;
 }
index 4ab59da..495092f 100644 (file)
@@ -311,7 +311,7 @@ static int ll_revalidate_dentry(struct dentry *dentry,
        CDEBUG(D_VFSTRACE, "VFS Op:name=%s, flags=%u\n",
               dentry->d_name.name, lookup_flags);
 
-       rc = ll_revalidate_d_crypto(dentry, lookup_flags);
+       rc = llcrypt_d_revalidate(dentry, lookup_flags);
        if (rc != 1)
                return rc;
 
index 47762ba..58e0441 100644 (file)
@@ -346,7 +346,7 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir)
               inode, (unsigned long)pos, i_size_read(inode), api32);
 
        if (IS_ENCRYPTED(inode)) {
-               rc = llcrypt_get_encryption_info(inode);
+               rc = llcrypt_prepare_readdir(inode);
                if (rc && rc != -ENOKEY)
                        GOTO(out, rc);
        }
@@ -529,7 +529,7 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
        if (ll_sbi_has_encrypt(sbi) &&
            (IS_ENCRYPTED(parent) ||
             unlikely(ll_sb_has_test_dummy_encryption(parent->i_sb)))) {
-               err = llcrypt_get_encryption_info(parent);
+               err = llcrypt_prepare_readdir(parent);
                if (err)
                        GOTO(out_op_data, err);
                if (!llcrypt_has_encryption_key(parent))
@@ -2402,22 +2402,12 @@ out_detach:
        case LL_IOC_REMOVE_ENCRYPTION_KEY:
                if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
                        return -EOPNOTSUPP;
-               rc = llcrypt_ioctl_remove_key(file, (void __user *)arg);
-#ifdef CONFIG_LL_ENCRYPTION
-               if (!rc)
-                       sptlrpc_enc_pool_del_user();
-#endif
-               return rc;
+               return llcrypt_ioctl_remove_key(file, (void __user *)arg);
        case LL_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
                if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
                        return -EOPNOTSUPP;
-               rc = llcrypt_ioctl_remove_key_all_users(file,
-                                                       (void __user *)arg);
-#ifdef CONFIG_LL_ENCRYPTION
-               if (!rc)
-                       sptlrpc_enc_pool_del_user();
-#endif
-               return rc;
+               return llcrypt_ioctl_remove_key_all_users(file,
+                                                         (void __user *)arg);
        case LL_IOC_GET_ENCRYPTION_KEY_STATUS:
                if (!ll_sbi_has_encrypt(ll_i2sbi(inode)))
                        return -EOPNOTSUPP;
index e25809e..15e5bb1 100644 (file)
@@ -2952,7 +2952,7 @@ static int fid2path_for_enc_file(struct inode *parent, char *gfpath,
                /* From here, we know parent is encrypted */
 
                if (enckey != 0) {
-                       rc = llcrypt_get_encryption_info(parent);
+                       rc = llcrypt_prepare_readdir(parent);
                        if (rc && rc != -ENOKEY) {
                                dput(de_parent);
                                break;
index 9ed03ca..d0e7840 100644 (file)
@@ -1821,6 +1821,8 @@ struct ll_digest_filename {
        char ldf_excerpt[LL_CRYPTO_BLOCK_SIZE];
 };
 
+int ll_prepare_lookup(struct inode *dir, struct dentry *de,
+                     struct llcrypt_name *fname, struct lu_fid *fid);
 int ll_setup_filename(struct inode *dir, const struct qstr *iname,
                      int lookup, struct llcrypt_name *fname,
                      struct lu_fid *fid);
@@ -1828,8 +1830,8 @@ int ll_fname_disk_to_usr(struct inode *inode,
                         u32 hash, u32 minor_hash,
                         struct llcrypt_str *iname, struct llcrypt_str *oname,
                         struct lu_fid *fid);
-int ll_revalidate_d_crypto(struct dentry *dentry, unsigned int flags);
 int ll_file_open_encrypt(struct inode *inode, struct file *filp);
+
 static inline char *xattr_for_enc(struct inode *inode)
 {
        if (ll_sbi_has_name_encrypt(ll_i2sbi(inode)))
@@ -1837,6 +1839,7 @@ static inline char *xattr_for_enc(struct inode *inode)
 
        return LL_XATTR_NAME_ENCRYPTION_CONTEXT_OLD;
 }
+
 #ifdef HAVE_LUSTRE_CRYPTO
 extern const struct llcrypt_operations lustre_cryptops;
 #endif
index b6f98e1..e59c84a 100644 (file)
@@ -526,7 +526,9 @@ retry_connect:
                        LCONSOLE_WARN("%s: server %s does not support name encryption, not using it.\n",
                                      sbi->ll_fsname,
                                      sbi->ll_md_exp->exp_obd->obd_name);
+#ifdef CONFIG_LL_ENCRYPTION
                lsi->lsi_flags &= ~LSI_FILENAME_ENC;
+#endif
                lsi->lsi_flags &= ~LSI_FILENAME_ENC_B64_OLD_CLI;
                ll_sbi_set_name_encrypt(sbi, false);
        }
@@ -1119,8 +1121,13 @@ static int ll_options(char *options, struct super_block *sb)
 #else
                        struct lustre_sb_info *lsi = s2lsi(sb);
 
-                       err = llcrypt_set_test_dummy_encryption(sb, &args[0],
-                                                               &lsi->lsi_dummy_enc_ctx);
+                       err = llcrypt_set_test_dummy_encryption(sb,
+#ifdef HAVE_FSCRYPT_SET_TEST_DUMMY_ENC_CHAR_ARG
+                                                               args->from,
+#else
+                                                               &args[0],
+#endif
+                                                               &lsi->lsi_dummy_enc_policy);
                        if (!err)
                                break;
 
@@ -1541,7 +1548,7 @@ skip_cleanup:
        }
 #endif
 
-       llcrypt_free_dummy_context(&lsi->lsi_dummy_enc_ctx);
+       llcrypt_free_dummy_policy(&lsi->lsi_dummy_enc_policy);
        ll_free_sbi(sb);
        lsi->lsi_llsbi = NULL;
 out_no_sbi:
index cc224b6..d5e7625 100644 (file)
@@ -1642,7 +1642,7 @@ static ssize_t ll_nosquash_nids_seq_write(struct file *file,
 
 LDEBUGFS_SEQ_FOPS(ll_nosquash_nids);
 
-#ifdef CONFIG_LL_ENCRYPTION
+#if defined(CONFIG_LL_ENCRYPTION)
 static int ll_filename_enc_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
@@ -1687,7 +1687,9 @@ static ssize_t ll_filename_enc_seq_write(struct file *file,
 }
 
 LDEBUGFS_SEQ_FOPS(ll_filename_enc);
+#endif /* CONFIG_LL_ENCRYPTION */
 
+#if defined(CONFIG_LL_ENCRYPTION) || defined(HAVE_LUSTRE_CRYPTO)
 static int ll_old_b64_enc_seq_show(struct seq_file *m, void *v)
 {
        struct super_block *sb = m->private;
@@ -1734,7 +1736,7 @@ static ssize_t ll_old_b64_enc_seq_write(struct file *file,
 }
 
 LDEBUGFS_SEQ_FOPS(ll_old_b64_enc);
-#endif /* CONFIG_LL_ENCRYPTION */
+#endif /* CONFIG_LL_ENCRYPTION || HAVE_LUSTRE_CRYPTO */
 
 static int ll_pcc_seq_show(struct seq_file *m, void *v)
 {
@@ -1793,6 +1795,8 @@ struct ldebugfs_vars lprocfs_llite_obd_vars[] = {
 #ifdef CONFIG_LL_ENCRYPTION
        { .name =       "enable_filename_encryption",
          .fops =       &ll_filename_enc_fops,                  },
+#endif
+#if defined(CONFIG_LL_ENCRYPTION) || defined(HAVE_LUSTRE_CRYPTO)
        { .name =       "filename_enc_use_old_base64",
          .fops =       &ll_old_b64_enc_fops,                   },
 #endif
index 14ea40c..2681bf6 100644 (file)
@@ -693,7 +693,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                                              ll_i2sbi(inode)->ll_fsname,
                                              PFID(ll_inode2fid(inode)), rc);
                                else if (encrypt) {
-                                       rc = llcrypt_get_encryption_info(inode);
+                                       rc = llcrypt_prepare_readdir(inode);
                                        if (rc)
                                                CDEBUG(D_SEC,
                                                 "cannot get enc info for "DFID": rc = %d\n",
@@ -755,7 +755,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                }
 
                if (encrypt) {
-                       rc = llcrypt_get_encryption_info(inode);
+                       rc = llcrypt_prepare_readdir(inode);
                        if (rc)
                                GOTO(out, rc);
                        if (!llcrypt_has_encryption_key(inode))
@@ -855,23 +855,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
        else
                opc = LUSTRE_OPC_LOOKUP;
 
-       /* Here we should be calling llcrypt_prepare_lookup(). But it installs a
-        * custom ->d_revalidate() method, so we lose ll_d_ops.
-        * To workaround this, call ll_setup_filename() and do the rest
-        * manually. Also make a copy of llcrypt_d_revalidate() (unfortunately
-        * not exported function) and call it from ll_revalidate_dentry(), to
-        * ensure we do not cache stale dentries after a key has been added.
-        */
-       rc = ll_setup_filename(parent, &dentry->d_name, 1, &fname, &fid);
-       if ((!rc || rc == -ENOENT) && fname.is_ciphertext_name) {
-               spin_lock(&dentry->d_lock);
-               dentry->d_flags |= DCACHE_NOKEY_NAME;
-               spin_unlock(&dentry->d_lock);
-       }
-       if (rc == -ENOENT)
-               RETURN(NULL);
+       rc = ll_prepare_lookup(parent, dentry, &fname, &fid);
        if (rc)
-               RETURN(ERR_PTR(rc));
+               RETURN(rc != -ENOENT ? ERR_PTR(rc) : NULL);
 
        op_data = ll_prep_md_op_data(NULL, parent, NULL, fname.disk_name.name,
                                     fname.disk_name.len, 0, opc, NULL);
@@ -1227,7 +1213,7 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
                /* in case of create, this is going to be a regular file because
                 * we set S_IFREG bit on it->it_create_mode above
                 */
-               rc = llcrypt_get_encryption_info(dir);
+               rc = llcrypt_prepare_readdir(dir);
                if (rc)
                        GOTO(out_release, rc);
                if (open_flags & O_CREAT) {
@@ -1572,7 +1558,7 @@ again:
            (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) ||
             (unlikely(ll_sb_has_test_dummy_encryption(dir->i_sb)) &&
              S_ISDIR(mode)))) {
-               err = llcrypt_get_encryption_info(dir);
+               err = llcrypt_prepare_readdir(dir);
                if (err)
                        GOTO(err_exit, err);
                if (!llcrypt_has_encryption_key(dir))
index 3a2a8bf..1bf1f8a 100644 (file)
@@ -1138,10 +1138,6 @@ void gss_sec_destroy_common(struct gss_sec *gsec)
        }
 
        class_import_put(sec->ps_import);
-
-       if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV)
-               sptlrpc_enc_pool_del_user();
-
        EXIT;
 }
 
index bdb65dd..cc4c06d 100644 (file)
@@ -798,12 +798,6 @@ int sptlrpc_enc_pool_add_user(void)
 }
 EXPORT_SYMBOL(sptlrpc_enc_pool_add_user);
 
-int sptlrpc_enc_pool_del_user(void)
-{
-       return 0;
-}
-EXPORT_SYMBOL(sptlrpc_enc_pool_del_user);
-
 static inline void enc_pools_alloc(void)
 {
        LASSERT(page_pools.epp_max_pools);