#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2017 Google, Inc. All Rights Reserved. # # FS QA Test No. 440 # # Test that when the filesystem tries to enforce that all files in a directory # tree use the same encryption policy, it doesn't get confused and incorrectly # return EPERM in cases where the parent's key is cached but not the child's, or # vice versa. Such situations can arise following removal of the master key # from the keyring. Regression test for: # 272f98f68462 ("fscrypt: fix context consistency check when key(s) unavailable") # seq=`basename $0` seqres=$RESULT_DIR/$seq echo "QA output created by $seq" here=`pwd` tmp=/tmp/$$ status=1 # failure is the default! trap "_cleanup; exit \$status" 0 1 2 3 15 _cleanup() { cd / rm -f $tmp.* } # get standard environment, filters and checks . ./common/rc . ./common/filter . ./common/encrypt # remove previous $seqres.full before test rm -f $seqres.full # real QA test starts here _supported_fs generic _supported_os Linux _require_scratch_encryption _require_command "$KEYCTL_PROG" keyctl # Set up an encryption-capable filesystem and an encryption key. _new_session_keyring _scratch_mkfs_encrypted &>> $seqres.full _scratch_mount keydesc=$(_generate_key_descriptor) raw_key=$(_generate_raw_encryption_key) _add_encryption_key $keydesc $raw_key # Set up an encrypted directory containing a regular file, a subdirectory, and a # symlink. mkdir $SCRATCH_MNT/edir _set_encpolicy $SCRATCH_MNT/edir $keydesc mkdir $SCRATCH_MNT/edir/subdir ln -s target $SCRATCH_MNT/edir/symlink echo contents > $SCRATCH_MNT/edir/file # Starting from a fresh mount (no inodes have their encryption key cached), # reproduce the situation where an encrypted file *without* its key cached is # looked up or opened from within a directory *with* its key cached, and no key # is in the keyring. Try with a regular file, a directory, and a symlink. _scratch_cycle_mount echo echo "***** Parent has key, but child doesn't *****" exec 3< $SCRATCH_MNT/edir # pin inode with cached key in memory ls $SCRATCH_MNT/edir | sort _unlink_encryption_key $keydesc cat $SCRATCH_MNT/edir/file |& _filter_scratch ls $SCRATCH_MNT/edir/subdir cat $SCRATCH_MNT/edir/symlink |& _filter_scratch exec 3>&- # Now, the inverse: an encrypted file *with* its key cached is looked up or # opened from within a directory *without* its key cached, and no key is in the # keyring. This is most easily reproducible using a hard link. Note: the # expected behavior (at least, until we have a real API for revoking filesystem # encryption keys) is that we should still be able to open the file and read its # plaintext contents, even though its filename is shown in ciphertext! echo echo "***** Child has key, but parent doesn't *****" _add_encryption_key $keydesc $raw_key mkdir $SCRATCH_MNT/edir2 _set_encpolicy $SCRATCH_MNT/edir2 $keydesc ln $SCRATCH_MNT/edir/file $SCRATCH_MNT/edir2/link _scratch_cycle_mount cat $SCRATCH_MNT/edir2/link exec 3< $SCRATCH_MNT/edir2/link # pin inode with cached key in memory _unlink_encryption_key $keydesc stat $SCRATCH_MNT/edir/file |& _filter_scratch cat "$(find $SCRATCH_MNT/edir/ -type f)" exec 3>&- # success, all done status=0 exit