From: James Simmons Date: Wed, 8 Feb 2023 13:04:45 +0000 (-0500) Subject: LU-15420 sec: handle simple fscrypt changes for 5.15 kernels X-Git-Tag: 2.15.55~140 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=048e2cc7d2d52870a48c4df2abd3944114c96271;p=fs%2Flustre-release.git LU-15420 sec: handle simple fscrypt changes for 5.15 kernels 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 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49125 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Sebastien Buisson Reviewed-by: Shaun Tancheff Reviewed-by: Oleg Drokin --- diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 0f73072..c7c4d4b 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -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 +],[ + 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 +],[ + 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 +],[ + 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 +],[ + 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 +],[ + 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 +],[ + 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 diff --git a/lustre/include/lustre_crypto.h b/lustre/include/lustre_crypto.h index d048470..4eca297 100644 --- a/lustre/include/lustre_crypto.h +++ b/lustre/include/lustre_crypto.h @@ -33,6 +33,11 @@ #define __FS_HAS_ENCRYPTION 1 #include +/* 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 @@ -42,10 +47,21 @@ #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) \ @@ -56,7 +72,11 @@ 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) @@ -82,8 +102,13 @@ __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) \ @@ -115,14 +140,19 @@ #else /* HAVE_LUSTRE_CRYPTO && !CONFIG_LL_ENCRYPTION */ #include + +#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 */ diff --git a/lustre/include/lustre_disk.h b/lustre/include/lustre_disk.h index e73ce1f..544cec2 100644 --- a/lustre/include/lustre_disk.h +++ b/lustre/include/lustre_disk.h @@ -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)) diff --git a/lustre/include/lustre_sec.h b/lustre/include/lustre_sec.h index 831d351..0db5e65 100644 --- a/lustre/include/lustre_sec.h +++ b/lustre/include/lustre_sec.h @@ -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); diff --git a/lustre/llite/crypto.c b/lustre/llite/crypto.c index 37a2153..d93f22c 100644 --- a/lustre/llite/crypto.c +++ b/lustre/llite/crypto.c @@ -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; } diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index 4ab59da0..495092f 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -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; diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 47762ba..58e0441 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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; diff --git a/lustre/llite/file.c b/lustre/llite/file.c index e25809e..15e5bb1 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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; diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 9ed03ca..d0e7840 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -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 diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index b6f98e1..e59c84a 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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: diff --git a/lustre/llite/lproc_llite.c b/lustre/llite/lproc_llite.c index cc224b6..d5e7625 100644 --- a/lustre/llite/lproc_llite.c +++ b/lustre/llite/lproc_llite.c @@ -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 diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 14ea40c..2681bf6 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -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)) diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index 3a2a8bf..1bf1f8a 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -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; } diff --git a/lustre/ptlrpc/sec_bulk.c b/lustre/ptlrpc/sec_bulk.c index bdb65dd..cc4c06d 100644 --- a/lustre/ptlrpc/sec_bulk.c +++ b/lustre/ptlrpc/sec_bulk.c @@ -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);