unsigned int max_len,
struct llcrypt_str *disk_link)
{
- if ((IS_ENCRYPTED(dir) &&
- llcrypt_policy_has_filename_enc(dir)) ||
- llcrypt_dummy_context_enabled(dir))
+ if ((IS_ENCRYPTED(dir) || llcrypt_dummy_context_enabled(dir)) &&
+ llcrypt_policy_has_filename_enc(dir))
return __llcrypt_prepare_symlink(dir, len, max_len, disk_link);
disk_link->name = (unsigned char *)target;
memset(&ctx, 0, sizeof(ctx));
ctx.version = LLCRYPT_CONTEXT_V1;
ctx.v1.contents_encryption_mode = LLCRYPT_MODE_AES_256_XTS;
- ctx.v1.filenames_encryption_mode = LLCRYPT_MODE_AES_256_CTS;
+ if (lsi->lsi_flags & LSI_FILENAME_ENC) {
+ ctx.v1.filenames_encryption_mode =
+ LLCRYPT_MODE_AES_256_CTS;
+ } else {
+ llcrypt_warn(inode,
+ "dummy enc: forcing filenames_encryption_mode to null");
+ ctx.v1.filenames_encryption_mode = LLCRYPT_MODE_NULL;
+ }
memset(ctx.v1.master_key_descriptor, 0x42,
LLCRYPT_KEY_DESCRIPTOR_SIZE);
res = sizeof(ctx.v1);
bool ll_sb_has_test_dummy_encryption(struct super_block *sb);
bool ll_sbi_has_encrypt(struct ll_sb_info *sbi);
void ll_sbi_set_encrypt(struct ll_sb_info *sbi, bool set);
+bool ll_sbi_has_name_encrypt(struct ll_sb_info *sbi);
+void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set);
/* sizeof(struct fscrypt_context_v2) = 40 */
#define LLCRYPT_ENC_CTX_SIZE 40
#define OBD_CONNECT2_BATCH_RPC 0x400000ULL /* Multi-RPC batch request */
#define OBD_CONNECT2_PCCRO 0x800000ULL /* Read-only PCC */
#define OBD_CONNECT2_ATOMIC_OPEN_LOCK 0x4000000ULL/* request lock on 1st open */
+#define OBD_CONNECT2_ENCRYPT_NAME 0x8000000ULL /* name encrypt */
/* XXX README XXX:
* Please DO NOT add flag values here before first ensuring that this same
* flag value is not in use on some other branch. Please clear any such
OBD_CONNECT2_GETATTR_PFID |\
OBD_CONNECT2_LSEEK | OBD_CONNECT2_DOM_LVB |\
OBD_CONNECT2_REP_MBITS | \
- OBD_CONNECT2_ATOMIC_OPEN_LOCK)
+ OBD_CONNECT2_ATOMIC_OPEN_LOCK | \
+ OBD_CONNECT2_ENCRYPT_NAME)
#define OST_CONNECT_SUPPORTED (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
/* Get enc context xattr directly instead of going through the VFS,
* as there is no xattr handler for "encryption.".
*/
- rc = ll_xattr_list(inode, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ rc = ll_xattr_list(inode, xattr_for_enc(inode),
XATTR_ENCRYPTION_T, ctx, len, OBD_MD_FLXATTR);
/* used as encryption unit size */
if (encctx && encctxlen)
rc = ll_xattr_cache_insert(inode,
- LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ xattr_for_enc(inode),
encctx, encctxlen);
if (rc)
return rc;
* through the VFS, as there is no xattr handler for "encryption.".
*/
rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode),
- OBD_MD_FLXATTR, LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ OBD_MD_FLXATTR, xattr_for_enc(inode),
ctx, len, XATTR_CREATE, ll_i2suppgid(inode), &req);
if (rc)
return rc;
}
}
+bool ll_sbi_has_name_encrypt(struct ll_sb_info *sbi)
+{
+ return test_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
+}
+
+void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set)
+{
+ if (set)
+ set_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
+ else
+ clear_bit(LL_SBI_ENCRYPT_NAME, sbi->ll_flags);
+}
+
static bool ll_empty_dir(struct inode *inode)
{
/* used by llcrypt_ioctl_set_policy(), because a policy can only be set
{
}
+bool ll_sbi_has_name_encrypt(struct ll_sb_info *sbi)
+{
+ return false;
+}
+
+void ll_sbi_set_name_encrypt(struct ll_sb_info *sbi, bool set)
+{
+}
+
int ll_setup_filename(struct inode *dir, const struct qstr *iname,
int lookup, struct llcrypt_name *fname,
struct lu_fid *fid)
#endif
}
+static inline bool obd_connect_has_name_enc(struct obd_connect_data *data)
+{
+#ifdef HAVE_LUSTRE_CRYPTO
+ return data->ocd_connect_flags & OBD_CONNECT_FLAGS2 &&
+ data->ocd_connect_flags2 & OBD_CONNECT2_ENCRYPT_NAME;
+#else
+ return false;
+#endif
+}
+
+static inline void obd_connect_set_name_enc(struct obd_connect_data *data)
+{
+#ifdef HAVE_LUSTRE_CRYPTO
+ data->ocd_connect_flags2 |= OBD_CONNECT2_ENCRYPT_NAME;
+#endif
+}
+
/*
* Locking to guarantee consistency of non-atomic updates to long long i_size,
* consistency between file size and KMS.
LL_SBI_TINY_WRITE, /* tiny write support */
LL_SBI_FILE_HEAT, /* file heat support */
LL_SBI_PARALLEL_DIO, /* parallel (async) O_DIRECT RPCs */
+ LL_SBI_ENCRYPT_NAME, /* name encryption */
LL_SBI_NUM_FLAGS
};
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;
+
+ return LL_XATTR_NAME_ENCRYPTION_CONTEXT_OLD;
+}
#ifdef HAVE_LUSTRE_CRYPTO
extern const struct llcrypt_operations lustre_cryptops;
#endif
set_bit(LL_SBI_TINY_WRITE, sbi->ll_flags);
set_bit(LL_SBI_PARALLEL_DIO, sbi->ll_flags);
ll_sbi_set_encrypt(sbi, true);
+ ll_sbi_set_name_encrypt(sbi, true);
/* root squash */
sbi->ll_squash.rsi_uid = 0;
data->ocd_connect_flags &= ~OBD_CONNECT_PINGLESS;
obd_connect_set_secctx(data);
- if (ll_sbi_has_encrypt(sbi))
+ if (ll_sbi_has_encrypt(sbi)) {
+ obd_connect_set_name_enc(data);
obd_connect_set_enc(data);
+ }
#if defined(CONFIG_SECURITY)
data->ocd_connect_flags2 |= OBD_CONNECT2_SELINUX_POLICY;
ll_sbi_set_encrypt(sbi, false);
}
+ if (ll_sbi_has_name_encrypt(sbi) && !obd_connect_has_name_enc(data)) {
+ struct lustre_sb_info *lsi = s2lsi(sb);
+
+ if (ll_sb_has_test_dummy_encryption(sb))
+ 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);
+ lsi->lsi_flags &= ~LSI_FILENAME_ENC;
+ ll_sbi_set_name_encrypt(sbi, false);
+ }
+
if (data->ocd_ibits_known & MDS_INODELOCK_XATTR) {
if (!(data->ocd_connect_flags & OBD_CONNECT_MAX_EASIZE)) {
LCONSOLE_INFO("%s: disabling xattr cache due to "
{LL_SBI_TINY_WRITE, "tiny_write"},
{LL_SBI_FILE_HEAT, "file_heat"},
{LL_SBI_PARALLEL_DIO, "parallel_dio"},
+ {LL_SBI_ENCRYPT_NAME, "name_encrypt"},
};
int ll_sbi_flags_seq_show(struct seq_file *m, void *v)
if (err)
GOTO(out_free_cfg, err);
+ if (ll_sb_has_test_dummy_encryption(sb))
+ /* enable filename encryption by default for dummy enc mode */
+ lsi->lsi_flags |= LSI_FILENAME_ENC;
+ else
+ /* filename encryption is disabled by default */
+ lsi->lsi_flags &= ~LSI_FILENAME_ENC;
+
/* kernel >= 2.6.38 store dentry operations in sb->s_d_op. */
sb->s_d_op = &ll_d_ops;
struct seq_file *m = file->private_data;
struct super_block *sb = m->private;
struct lustre_sb_info *lsi = s2lsi(sb);
+ struct ll_sb_info *sbi = ll_s2sbi(sb);
bool val;
int rc;
if (rc)
return rc;
- if (val)
+ if (val) {
+ if (!ll_sbi_has_name_encrypt(sbi)) {
+ /* server does not support name encryption,
+ * so force it to NULL on client
+ */
+ CDEBUG(D_SEC, "%s: server does not support name encryption\n",
+ sbi->ll_fsname);
+ lsi->lsi_flags &= ~LSI_FILENAME_ENC;
+ return -EOPNOTSUPP;
+ }
+
lsi->lsi_flags |= LSI_FILENAME_ENC;
- else
+ } else {
lsi->lsi_flags &= ~LSI_FILENAME_ENC;
+ }
return count;
}
"server returned encryption ctx for "DFID"\n",
PFID(ll_inode2fid(inode)));
rc = ll_xattr_cache_insert(inode,
- LL_XATTR_NAME_ENCRYPTION_CONTEXT,
+ xattr_for_enc(inode),
encctx, encctxlen);
if (rc)
CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n",
"server returned encryption ctx for "DFID"\n",
PFID(ll_inode2fid(child)));
rc = ll_xattr_cache_insert(child,
- LL_XATTR_NAME_ENCRYPTION_CONTEXT,
- encctx, encctxlen);
+ xattr_for_enc(child),
+ encctx, encctxlen);
if (rc)
CWARN("%s: cannot set enc ctx for "DFID": rc = %d\n",
ll_i2sbi(child)->ll_fsname,
}
CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
- /* filename encryption is disabled by default */
- lsi->lsi_flags &= ~LSI_FILENAME_ENC;
rc = lustre_start_mgc(sb);
if (rc) {
lustre_common_put_super(sb);
ENTRY;
if (ll_xattr_cache_find(cache, xattr_name, &xattr) == 0) {
- if (!strcmp(xattr_name, LL_XATTR_NAME_ENCRYPTION_CONTEXT))
+ if (!strcmp(xattr_name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) ||
+ !strcmp(xattr_name, LL_XATTR_NAME_ENCRYPTION_CONTEXT_OLD))
/* it means enc ctx was already in cache,
* ignore error as it cannot be modified
*/
GOTO(out_empty, 0);
list_for_each_entry_safe(entry, n, &lli->lli_xattrs, xe_list) {
- if (strcmp(entry->xe_name,
- LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0)
+ if (strcmp(entry->xe_name, xattr_for_enc(inode)) == 0)
continue;
CDEBUG(D_CACHE, "delete: %s\n", entry->xe_name);
* cache if we are just interested in encryption context.
*/
if ((valid & OBD_MD_FLXATTRLS ||
- strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) != 0) &&
+ strcmp(name, xattr_for_enc(inode)) != 0) &&
!ll_xattr_cache_filled(lli)) {
up_read(&lli->lli_xattrs_list_rwsem);
rc = ll_xattr_cache_refill(inode);
"mne_nid_type", /* 0x1000000 */
"lock_contend", /* 0x2000000 */
"atomic_open_lock", /* 0x4000000 */
+ "name_encryption", /* 0x8000000 */
NULL
};
OBD_CONNECT2_PCCRO);
LASSERTF(OBD_CONNECT2_ATOMIC_OPEN_LOCK == 0x4000000ULL, "found 0x%.16llxULL\n",
OBD_CONNECT2_ATOMIC_OPEN_LOCK);
+ LASSERTF(OBD_CONNECT2_ENCRYPT_NAME == 0x8000000ULL, "found 0x%.16llxULL\n",
+ OBD_CONNECT2_ENCRYPT_NAME);
LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)OBD_CKSUM_CRC32);
LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",
local lsfile=$TMP/lsfile
local scrambleddir
local scrambledfile
+ local inum
$LCTL get_param mdc.*.import | grep -q client_encryption ||
skip "client encryption not supported"
else
mkdir $testdir2
fi
+ inum=$(stat -c %i $testdir2)
if [ "$mds1_FSTYPE" = ldiskfs ]; then
# For now, restrict this part of the test to ldiskfs backend,
# as osd-zfs does not support 255 byte-long encrypted names.
remount_client_normally
# this is $testdir2
- scrambleddir=$(find $DIR/$tdir/ -maxdepth 1 -mindepth 1 -type d| grep _)
+ scrambleddir=$(find $DIR/$tdir/ -maxdepth 1 -mindepth 1 -inum $inum)
stat $scrambleddir || error "stat $scrambleddir failed"
if [ "$mds1_FSTYPE" = ldiskfs ]; then
stat $scrambleddir/* || error "cannot stat in $scrambleddir"
local testfile=$DIR/$tdir/$tfile
local testfile2=$DIR/$tdir/${tfile}.2
local tmpfile=$DIR/junk
+ local name_enc=1
local scrambleddir
local scrambledfile
mount.lustre --help |& grep -q "test_dummy_encryption:" ||
skip "need dummy encryption support"
+ $LCTL get_param mdc.*.connect_flags | grep -q name_encryption ||
+ name_enc=0
+
stack_trap cleanup_for_enc_tests EXIT
setup_for_enc_tests
error "cannot read from hard link (2.2)"
rm -f $tmpfile
- # check we are limited in the number of hard links
- # we can create for encrypted files, to what can fit into LinkEA
- for i in $(seq 1 160); do
- ln $testfile2 ${testfile}_$i || break
- done
- [ $i -lt 160 ] || error "hard link $i should fail"
- rm -f ${testfile}_*
+ if [ $name_enc -eq 1 ]; then
+ # check we are limited in the number of hard links
+ # we can create for encrypted files, to what can fit into LinkEA
+ for i in $(seq 1 160); do
+ ln $testfile2 ${testfile}_$i || break
+ done
+ [ $i -lt 160 ] || error "hard link $i should fail"
+ rm -f ${testfile}_*
+ fi
mrename $testfile2 $tmpfile &&
error "rename from encrypted to unencrypted dir should fail"
[ $(stat -c %s $scrambledlink) -eq \
$(expr length "$(readlink $scrambledlink)") ] ||
error "wrong symlink size without key"
- readlink -e $scrambledlink &&
- error "link should not point to anywhere useful"
+ if [ $name_enc -eq 1 ]; then
+ readlink -e $scrambledlink &&
+ error "link should not point to anywhere useful"
+ fi
ln -s $scrambledfile ${scrambledfile}.sym &&
error "symlink without key should fail (1)"
ln -s $tmpfile ${scrambledfile}.sl &&
trace_cmd $LFS migrate -m 0 $dirname/d2
echo b > $dirname/d2/subf
sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
- # migrate a non-empty encrypted dir
- trace_cmd $LFS migrate -m 1 $dirname/d2
- sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
- [ -f $dirname/d2/subf ] || error "migrate failed (1)"
- [ $(cat $dirname/d2/subf) == "b" ] || error "migrate failed (2)"
+ if (( "$MDS1_VERSION" > $(version_code 2.14.54.54) )); then
+ # migrate a non-empty encrypted dir
+ trace_cmd $LFS migrate -m 1 $dirname/d2
+ sync ; sync ; echo 3 > /proc/sys/vm/drop_caches
+ [ -f $dirname/d2/subf ] || error "migrate failed (1)"
+ [ $(cat $dirname/d2/subf) == "b" ] ||
+ error "migrate failed (2)"
+ fi
$LFS setdirstripe -i 1 -c 1 $dirname/d3
dirname=$dirname/d3/subdir
local testfile2=$testdir/${tfile}withveryverylongnametoexercisecode
local tmpfile=$TMP/${tfile}.tmp
local resfile=$TMP/${tfile}.res
- local nameenc
+ local nameenc=""
local fid1
local fid2
[ $filecount -eq 3 ] || error "found $filecount files"
# check enable_filename_encryption default value
- nameenc=$(lctl get_param -n llite.*.enable_filename_encryption |
+ $LCTL get_param mdc.*.connect_flags | grep -q name_encryption &&
+ nameenc=$(lctl get_param -n llite.*.enable_filename_encryption |
head -n1)
- [ $nameenc -eq 0 ] ||
- error "enable_filename_encryption should be 0 by default"
-
- # $testfile and $testfile2 should exist because names are not encrypted
- [ -f $testfile ] ||
- error "$testfile should exist because name is not encrypted"
- [ -f $testfile2 ] ||
- error "$testfile should exist because name is not encrypted"
+ if [ -n "$nameenc" ]; then
+ [ $nameenc -eq 0 ] ||
+ error "enable_filename_encryption should be 0 by default"
+
+ # $testfile and $testfile2 should exist because
+ # names are not encrypted
+ [ -f $testfile ] ||
+ error "$testfile should exist because name not encrypted"
+ [ -f $testfile2 ] ||
+ error "$testfile2 should exist because name not encrypted"
+ fi
scrambledfiles=( $(find $testdir/ -maxdepth 1 -type f) )
$RUNAS hexdump -C ${scrambledfiles[0]} &&
# server local client incompatible with SSK keys installed
if [ "$SHARED_KEY" != true ]; then
mount_mds_client
+ stack_trap umount_mds_client EXIT
do_facet $SINGLEMDS touch $DIR2/$tdir/newfile
mdsscrambledfile=$(do_facet $SINGLEMDS find $testdir2/ \
-maxdepth 1 -type f | head -n1)
do_facet $SINGLEMDS mrename "$mdsscrambledfile" $testdir2/fB &&
error "mrename $mdsscrambledfile should fail on MDS"
do_facet $SINGLEMDS rm -f $DIR2/$tdir/newfile
- umount_mds_client
fi
echo mypass | $RUNAS fscrypt unlock --verbose $testdir ||
echo "With FILESET $tdir, .fscrypt FID is $fid1"
# enable name encryption
- do_facet mgs $LCTL set_param -P llite.*.enable_filename_encryption=1
- [ $? -eq 0 ] ||
- error "set_param -P llite.*.enable_filename_encryption failed"
-
- wait_update_facet --verbose client \
- "$LCTL get_param -n llite.*.enable_filename_encryption | head -n1" \
- 1 30 ||
- error "enable_filename_encryption not set on client"
+ if [ -n "$nameenc" ]; then
+ do_facet mgs $LCTL set_param -P \
+ llite.*.enable_filename_encryption=1
+ [ $? -eq 0 ] ||
+ error "set_param -P \
+ llite.*.enable_filename_encryption failed"
+
+ wait_update_facet --verbose client \
+ "$LCTL get_param -n llite.*.enable_filename_encryption \
+ | head -n1" 1 30 ||
+ error "enable_filename_encryption not set on client"
+ fi
# encrypt 'vault' dir inside the subdir mount
echo -e 'mypass\nmypass' | su - $USER0 -c "fscrypt encrypt --verbose \
error "fscrypt lock $testdir failed (4)"
# encfile should actually have its name encrypted
- [ -f $testdir/encfile ] && error "encfile name should be encrypted"
+ if [ -n "$nameenc" ]; then
+ [ -f $testdir/encfile ] &&
+ error "encfile name should be encrypted"
+ fi
filecount=$(find $testdir -type f | wc -l)
[ $filecount -eq 1 ] || error "found $filecount files instead of 1"
error "fscrypt lock $DIR/$tdir/vault failed (5)"
# disable name encryption
- do_facet mgs $LCTL set_param -P llite.*.enable_filename_encryption=0
- [ $? -eq 0 ] ||
- error "set_param -P llite.*.enable_filename_encryption failed"
-
- wait_update_facet --verbose client \
- "$LCTL get_param -n llite.*.enable_filename_encryption | head -n1" \
- 0 30 ||
- error "enable_filename_encryption not set back to default"
+ if [ -n "$nameenc" ]; then
+ do_facet mgs $LCTL set_param -P \
+ llite.*.enable_filename_encryption=0
+ [ $? -eq 0 ] ||
+ error "set_param -P \
+ llite.*.enable_filename_encryption failed"
+
+ wait_update_facet --verbose client \
+ "$LCTL get_param -n llite.*.enable_filename_encryption \
+ | head -n1" 0 30 ||
+ error "enable_filename_encryption not set back to default"
+ fi
rm -rf $tmpfile $MOUNT/.fscrypt
}
[[ $MDSCOUNT -ge 2 ]] || skip_env "needs >= 2 MDTs"
- stack_trap "cleanup_for_enc_tests" EXIT
+ (( "$MDS1_VERSION" > $(version_code 2.14.54.54) )) ||
+ skip "MDT migration not supported with older server"
+
+ stack_trap cleanup_for_enc_tests EXIT
setup_for_enc_tests
$LFS setdirstripe -i 0 $dirname
CHECK_DEFINE_64X(OBD_CONNECT2_BATCH_RPC);
CHECK_DEFINE_64X(OBD_CONNECT2_PCCRO);
CHECK_DEFINE_64X(OBD_CONNECT2_ATOMIC_OPEN_LOCK);
+ CHECK_DEFINE_64X(OBD_CONNECT2_ENCRYPT_NAME);
CHECK_VALUE_X(OBD_CKSUM_CRC32);
CHECK_VALUE_X(OBD_CKSUM_ADLER);
OBD_CONNECT2_PCCRO);
LASSERTF(OBD_CONNECT2_ATOMIC_OPEN_LOCK == 0x4000000ULL, "found 0x%.16llxULL\n",
OBD_CONNECT2_ATOMIC_OPEN_LOCK);
+ LASSERTF(OBD_CONNECT2_ENCRYPT_NAME == 0x8000000ULL, "found 0x%.16llxULL\n",
+ OBD_CONNECT2_ENCRYPT_NAME);
LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
(unsigned)OBD_CKSUM_CRC32);
LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",