]) # 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
]) # 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
# 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
#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;
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 */
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
};
#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))
/* 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);
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
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
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
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);
}
/**
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;
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);
return valid;
}
+#endif /* !HAVE_FSCRYPT_D_REVALIDATE || CONFIG_LL_ENCRYPTION */
const struct llcrypt_operations lustre_cryptops = {
.key_prefix = "lustre:",
#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,
};
{
}
+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)
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;
}
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;
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);
}
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))
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;
/* 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;
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);
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)))
return LL_XATTR_NAME_ENCRYPTION_CONTEXT_OLD;
}
+
#ifdef HAVE_LUSTRE_CRYPTO
extern const struct llcrypt_operations lustre_cryptops;
#endif
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);
}
#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;
}
#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:
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;
}
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;
}
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)
{
#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
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",
}
if (encrypt) {
- rc = llcrypt_get_encryption_info(inode);
+ rc = llcrypt_prepare_readdir(inode);
if (rc)
GOTO(out, rc);
if (!llcrypt_has_encryption_key(inode))
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);
/* 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) {
(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))
}
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;
}
}
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);