Whamcloud - gitweb
LU-12275 sec: verify dir is empty when setting enc policy 17/39617/10
authorSebastien Buisson <sbuisson@ddn.com>
Tue, 11 Aug 2020 13:36:41 +0000 (22:36 +0900)
committerOleg Drokin <green@whamcloud.com>
Sat, 19 Sep 2020 14:11:55 +0000 (14:11 +0000)
When setting an encryption policy on a directory that we want to
be encrypted, make sure it is empty.
Otherwise return -ENOTEMPTY from server to client doing the ioctl.

Also add test to exercise the ioctl interface to get/set encryption
policies on directories, thanks to the fscrypt userspace tool.
And test the ability to lock an encrypted directory.

Fixes: 40d91eafe257 ("LU-12275 sec: atomicity of encryption context getting/setting")
Test-Parameters: testlist=sanity-sec envdefinitions=ONLY="36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 52 53 54" clientdistro=el8.1 fstype=ldiskfs mdscount=2 mdtcount=4
Test-Parameters: testlist=sanity-sec envdefinitions=ONLY="36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 52 53 54" clientdistro=el8.1 fstype=zfs mdscount=2 mdtcount=4
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: Iabffd24800314b12908f505d7e66492be7292a16
Reviewed-on: https://review.whamcloud.com/39617
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mdd/mdd_internal.h
lustre/tests/sanity-sec.sh

index 9081de1..aa7016e 100644 (file)
@@ -620,19 +620,23 @@ static inline int mdo_xattr_set(const struct lu_env *env,struct mdd_object *obj,
                                int fl, struct thandle *handle)
 {
        struct dt_object *next = mdd_object_child(obj);
                                int fl, struct thandle *handle)
 {
        struct dt_object *next = mdd_object_child(obj);
-       int rc;
+       int rc = 0;
 
        if (!mdd_object_exists(obj))
                return -ENOENT;
 
 
        if (!mdd_object_exists(obj))
                return -ENOENT;
 
-       rc = dt_xattr_set(env, next, buf, name, fl, handle);
-       if (rc >= 0 && strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) {
+       if ((strcmp(name, LL_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) &&
+           (!S_ISDIR(mdd_object_type(obj)) ||
+            (rc = mdd_dir_is_empty(env, obj)) == 0)) {
                struct lu_attr la = { 0 };
 
                la.la_valid = LA_FLAGS;
                la.la_flags = LUSTRE_ENCRYPT_FL;
                rc = dt_attr_set(env, next, &la, handle);
        }
                struct lu_attr la = { 0 };
 
                la.la_valid = LA_FLAGS;
                la.la_flags = LUSTRE_ENCRYPT_FL;
                rc = dt_attr_set(env, next, &la, handle);
        }
+       if (rc >= 0)
+               rc = dt_xattr_set(env, next, buf, name, fl, handle);
+
        return rc;
 }
 
        return rc;
 }
 
index b9a0e43..a866b66 100755 (executable)
@@ -3967,6 +3967,81 @@ test_53() {
 }
 run_test 53 "Mixed PAGE_SIZE clients"
 
 }
 run_test 53 "Mixed PAGE_SIZE clients"
 
+test_54() {
+       local testdir=$DIR/$tdir/$ID0
+       local testfile=$testdir/$tfile
+       local testfile2=$testdir/${tfile}2
+       local tmpfile=$TMP/${tfile}.tmp
+       local resfile=$TMP/${tfile}.res
+
+       $LCTL get_param mdc.*.import | grep -q client_encryption ||
+               skip "client encryption not supported"
+
+       mount.lustre --help |& grep -q "test_dummy_encryption:" ||
+               skip "need dummy encryption support"
+
+       which fscrypt || skip "This test needs fscrypt userspace tool"
+
+       fscrypt setup --force --verbose || error "fscrypt global setup failed"
+       sed -i 's/\(.*\)policy_version\(.*\):\(.*\)\"[0-9]*\"\(.*\)/\1policy_version\2:\3"2"\4/' \
+               /etc/fscrypt.conf
+       fscrypt setup --verbose $MOUNT || error "fscrypt setup $MOUNT failed"
+       mkdir -p $testdir
+       chown -R $ID0:$ID0 $testdir
+
+       echo -e 'mypass\nmypass' | su - $USER0 -c "fscrypt encrypt --verbose \
+               --source=custom_passphrase --name=protector $testdir" ||
+               error "fscrypt encrypt failed"
+
+       echo -e 'mypass\nmypass' | su - $USER0 -c "fscrypt encrypt --verbose \
+               --source=custom_passphrase --name=protector2 $testdir" &&
+               error "second fscrypt encrypt should have failed"
+
+       mkdir -p ${testdir}2 || error "mkdir ${testdir}2 failed"
+       touch ${testdir}2/f || error "mkdir ${testdir}2/f failed"
+       cancel_lru_locks
+
+       echo -e 'mypass\nmypass' | fscrypt encrypt --verbose \
+               --source=custom_passphrase --name=protector3 ${testdir}2 &&
+               error "fscrypt encrypt on non-empty dir should have failed"
+
+       $RUNAS dd if=/dev/urandom of=$testfile bs=127 count=1 conv=fsync ||
+               error "write to encrypted file $testfile failed"
+       cp $testfile $tmpfile
+       $RUNAS dd if=/dev/urandom of=$testfile2 bs=127 count=1 conv=fsync ||
+               error "write to encrypted file $testfile2 failed"
+
+       $RUNAS fscrypt lock --verbose $testdir ||
+               error "fscrypt lock $testdir failed (1)"
+
+       $RUNAS hexdump -C $testfile &&
+               error "reading $testfile should have failed without key"
+
+       echo mypass | $RUNAS fscrypt unlock --verbose $testdir ||
+               error "fscrypt unlock $testdir failed (1)"
+
+       $RUNAS cat $testfile > $resfile ||
+               error "reading $testfile failed"
+
+       cmp -bl $tmpfile $resfile || error "file read differs from file written"
+
+       $RUNAS fscrypt lock --verbose $testdir ||
+               error "fscrypt lock $testdir failed (2)"
+
+       $RUNAS hexdump -C $testfile2 &&
+               error "reading $testfile2 should have failed without key"
+
+       echo mypass | $RUNAS fscrypt unlock --verbose $testdir ||
+               error "fscrypt unlock $testdir failed (2)"
+
+       rm -rf $testdir/*
+       $RUNAS fscrypt lock --verbose $testdir ||
+               error "fscrypt lock $testdir failed (3)"
+
+       rm -f $tmpfile $resfile
+}
+run_test 54 "Encryption policies with fscrypt"
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {
 log "cleanup: ======================================================"
 
 sec_unsetup() {