Encrypted files created with Lustre 2.14 have clear text file names.
With new code implementing filename encryption, newly created files
will have cipher text names, unless they are in an encrypted directory
created in Lustre 2.14.
So we need to make sure llcrypt library can properly handle the "null"
algorithm for client side filename encryption, which is basically a
no-op.
Handling this "null" algo for filename encryption will not be possible
with the in-kernel fscrypt library, so modify the behaviour of
configure to build with embedded llcrypt by default, and only build
against in-kernel fscrypt if explicitly specified via
--enable-crypto=in-kernel configure option.
The objective is to urge users to convert their encrypted directories
to the new fashion that encrypts filenames.
However, with the new code some operations on encrypted files created
with 2.14 might not be possible, like migrate, so expressly forbid
migrate on files that use the "null" algorithm for client side
filename encryption.
Finally, we revert commit
11fcbfa9de4a5170abc2c5df2a6e4e02f0f84268
("LU-12275 sec: force file name encryption policy to null") so that
new encrypted directories will enforce filename encryption.
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I393945adc9b720a56544b5da0669cb2848507457
Reviewed-on: https://review.whamcloud.com/43388
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
extern int llcrypt_has_permitted_context(struct inode *, struct inode *);
extern int llcrypt_inherit_context(struct inode *, struct inode *,
void *, bool);
+extern bool llcrypt_policy_has_filename_enc(struct inode *inode);
/* keyring.c */
extern void llcrypt_sb_free(struct super_block *sb);
extern int llcrypt_ioctl_add_key(struct file *filp, void __user *arg);
{
return -EOPNOTSUPP;
}
+static inline bool llcrypt_policy_has_filename_enc(struct inode *inode)
+{
+ return false;
+}
/* keyring.c */
static inline void llcrypt_sb_free(struct super_block *sb)
unsigned int max_len,
struct llcrypt_str *disk_link)
{
- if (IS_ENCRYPTED(dir) || llcrypt_dummy_context_enabled(dir))
+ if ((IS_ENCRYPTED(dir) &&
+ likely(llcrypt_policy_has_filename_enc(dir))) ||
+ llcrypt_dummy_context_enabled(dir))
return __llcrypt_prepare_symlink(dir, len, max_len, disk_link);
disk_link->name = (unsigned char *)target;
u32 max_len, u32 *encrypted_len_ret)
{
const struct llcrypt_info *ci = llcrypt_info(inode);
+ struct crypto_skcipher *tfm = ci->ci_ctfm;
int padding = 4 << (llcrypt_policy_flags(&ci->ci_policy) &
LLCRYPT_POLICY_FLAGS_PAD_MASK);
u32 encrypted_len;
if (orig_len > max_len)
return false;
- encrypted_len = max(orig_len, (u32)LL_CRYPTO_BLOCK_SIZE);
- encrypted_len = round_up(encrypted_len, padding);
- *encrypted_len_ret = min(encrypted_len, max_len);
+ if (tfm == NULL) {
+ *encrypted_len_ret = orig_len;
+ } else {
+ encrypted_len = max(orig_len, (u32)LL_CRYPTO_BLOCK_SIZE);
+ encrypted_len = round_up(encrypted_len, padding);
+ *encrypted_len_ret = min(encrypted_len, max_len);
+ }
return true;
}
return 0;
}
- if (iname->len < LL_CRYPTO_BLOCK_SIZE)
- return -EUCLEAN;
+ if (llcrypt_has_encryption_key(inode)) {
+ struct llcrypt_info *ci = llcrypt_info(inode);
+ struct crypto_skcipher *tfm = ci->ci_ctfm;
+
+ if (tfm && iname->len < LL_CRYPTO_BLOCK_SIZE)
+ return -EUCLEAN;
- if (llcrypt_has_encryption_key(inode))
return fname_decrypt(inode, iname, oname);
+ }
+
+ if (unlikely(!llcrypt_policy_has_filename_enc(inode))) {
+ memcpy(oname->name, iname->name, iname->len);
+ oname->name[iname->len] = '\0';
+ oname->len = iname->len;
+ return 0;
+ }
if (iname->len <= LLCRYPT_FNAME_MAX_UNDIGESTED_SIZE) {
oname->len = base64_encode(iname->name, iname->len,
}
if (!lookup)
return -ENOKEY;
+
+ if (unlikely(!llcrypt_policy_has_filename_enc(dir))) {
+ fname->disk_name.name = (unsigned char *)iname->name;
+ fname->disk_name.len = iname->len;
+ return 0;
+ }
+
fname->is_ciphertext_name = true;
/*
struct llcrypt_symlink_data *sd;
unsigned int ciphertext_len;
+ if (unlikely(!llcrypt_policy_has_filename_enc(inode)))
+ return 0;
+
err = llcrypt_require_key(inode);
if (err)
return err;
* the ciphertext length, even though this is redundant with i_size.
*/
- if (max_size < sizeof(*sd))
- return ERR_PTR(-EUCLEAN);
- sd = caddr;
- cstr.name = (unsigned char *)sd->encrypted_path;
- cstr.len = le16_to_cpu(sd->len);
+ if (unlikely(!llcrypt_policy_has_filename_enc(inode))) {
+ cstr.name = (unsigned char *)caddr;
+ cstr.len = strlen(cstr.name);
+
+ if (cstr.len == 0)
+ return ERR_PTR(-EUCLEAN);
+ } else {
+ if (max_size < sizeof(*sd))
+ return ERR_PTR(-EUCLEAN);
+ sd = caddr;
+ cstr.name = (unsigned char *)sd->encrypted_path;
+ cstr.len = le16_to_cpu(sd->len);
- if (cstr.len == 0)
- return ERR_PTR(-EUCLEAN);
+ if (cstr.len == 0)
+ return ERR_PTR(-EUCLEAN);
- if (cstr.len + sizeof(*sd) - 1 > max_size)
- return ERR_PTR(-EUCLEAN);
+ if (cstr.len + sizeof(*sd) - 1 > max_size)
+ return ERR_PTR(-EUCLEAN);
+ }
err = llcrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
if (err)
/* Fake up a context for an unencrypted directory */
memset(&ctx, 0, sizeof(ctx));
ctx.version = LLCRYPT_CONTEXT_V1;
- /* Force file/directory name encryption policy to null.
- * This is needed for interoperability with future versions.
- * Change to be reverted back when Lustre supports name
- * encryption.
- */
- CWARN("inode %lu: setting policy filenames_encryption_mode to null\n",
- inode->i_ino);
ctx.v1.contents_encryption_mode = LLCRYPT_MODE_AES_256_XTS;
- ctx.v1.filenames_encryption_mode = LLCRYPT_MODE_NULL;
+ ctx.v1.filenames_encryption_mode = LLCRYPT_MODE_AES_256_CTS;
memset(ctx.v1.master_key_descriptor, 0x42,
LLCRYPT_KEY_DESCRIPTOR_SIZE);
res = sizeof(ctx.v1);
return lsi->lsi_cop->set_context(inode, &ctx, ctxsize, NULL);
}
+/* Tell if an inode's encryption policy has filename encryption */
+bool llcrypt_policy_has_filename_enc(struct inode *inode)
+{
+ union llcrypt_policy policy;
+ int err;
+
+ err = llcrypt_get_policy(inode, &policy);
+ if (err)
+ return true;
+
+ if ((policy.version == LLCRYPT_POLICY_V1 &&
+ policy.v1.filenames_encryption_mode == LLCRYPT_MODE_NULL) ||
+ (policy.version == LLCRYPT_POLICY_V2 &&
+ policy.v2.filenames_encryption_mode == LLCRYPT_MODE_NULL))
+ return false;
+ return true;
+}
+EXPORT_SYMBOL(llcrypt_policy_has_filename_enc);
+
int llcrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
{
union llcrypt_policy policy;
return -EFAULT;
policy.version = version;
- /* Force file/directory name encryption policy to null.
- * This is needed for interoperability with future versions.
- * Code to be removed when Lustre supports name encryption.
- */
- CWARN("inode %lu: forcing policy filenames_encryption_mode to null\n",
- inode->i_ino);
- switch (policy.version) {
- case LLCRYPT_POLICY_V1:
- policy.v1.filenames_encryption_mode = LLCRYPT_MODE_NULL;
- break;
- case LLCRYPT_POLICY_V2:
- policy.v2.filenames_encryption_mode = LLCRYPT_MODE_NULL;
- break;
- }
-
if (!inode_owner_or_capable(inode))
return -EACCES;
],[
fscrypt_ioctl_get_policy_ex(NULL, NULL);
],[
- dnl When Lustre supports file name encryption, restore "yes" value
- dnl for has_fscrypt_support and remove warning message.
- has_fscrypt_support="no"
- AC_MSG_WARN([
-This version of Lustre lacks file name encryption support,
-so it cannot make use of in-kernel fscrypt.
-Will use embedded llcrypt if possible.])
+ has_fscrypt_support="yes"
])
]) # LC_FSCRYPT_SUPPORT
AC_DEFUN([LC_CONFIG_CRYPTO], [
AC_MSG_CHECKING([whether to enable Lustre client crypto])
AC_ARG_ENABLE([crypto],
- AC_HELP_STRING([--enable-crypto],
- [enable Lustre client crypto]),
+ AC_HELP_STRING([--enable-crypto=yes|no|in-kernel],
+ [enable Lustre client crypto (default is yes), use 'in-kernel' to force use of in-kernel fscrypt instead of embedded llcrypt]),
[], [enable_crypto="auto"])
AS_IF([test "x$enable_crypto" != xno -a "x$enable_dist" = xno], [
AC_MSG_RESULT(
)
LC_IS_ENCRYPTED
LC_FSCRYPT_SUPPORT])
-AS_IF([test "x$has_fscrypt_support" = xyes], [
- AC_DEFINE(HAVE_LUSTRE_CRYPTO, 1, [Enable Lustre client crypto via in-kernel fscrypt])
- enable_crypto=yes],
+AS_IF([test "x$enable_crypto" = xin-kernel], [
+ AS_IF([test "x$has_fscrypt_support" = xyes], [
+ AC_DEFINE(HAVE_LUSTRE_CRYPTO, 1, [Enable Lustre client crypto via in-kernel fscrypt])], [
+ AC_MSG_ERROR([Lustre client crypto cannot be enabled via in-kernel fscrypt.])
+ enable_crypto=no])],
[AS_IF([test "x$has_is_encrypted" = xyes], [
AC_DEFINE(HAVE_LUSTRE_CRYPTO, 1, [Enable Lustre client crypto via embedded llcrypt])
AC_DEFINE(CONFIG_LL_ENCRYPTION, 1, [embedded llcrypt])
- enable_crypto=yes
+ enable_crypto="embedded llcrypt"
enable_llcrypt=yes], [
AS_IF([test "x$enable_crypto" = xyes],
[AC_MSG_ERROR([Lustre client crypto cannot be enabled because of lack of encryption support in your kernel.])])
#define llcrypt_ioctl_set_policy(filp, arg) fscrypt_ioctl_set_policy(filp, arg)
#define llcrypt_ioctl_get_policy_ex(filp, arg) \
fscrypt_ioctl_get_policy_ex(filp, arg)
+#define llcrypt_policy_has_filename_enc(inode) true
#define llcrypt_ioctl_add_key(filp, arg) fscrypt_ioctl_add_key(filp, arg)
#define llcrypt_ioctl_remove_key(filp, arg) fscrypt_ioctl_remove_key(filp, arg)
#define llcrypt_ioctl_remove_key_all_users(filp, arg) \
PFID(ll_inode2fid(child_inode)));
GOTO(out_iput, rc = -ENOKEY);
}
+ if (unlikely(!llcrypt_policy_has_filename_enc(child_inode))) {
+ CDEBUG(D_SEC,
+ "cannot migrate old format encrypted "DFID", please move to new enc dir first\n",
+ PFID(ll_inode2fid(child_inode)));
+ GOTO(out_iput, rc = -EUCLEAN);
+ }
}
op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,