|  | #! /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") | 
|  | # | 
|  | . ./common/preamble | 
|  | _begin_fstest auto quick encrypt | 
|  |  | 
|  | # Import common functions. | 
|  | . ./common/filter | 
|  | . ./common/encrypt | 
|  |  | 
|  | _require_scratch_encryption | 
|  | _require_symlinks | 
|  | _require_command "$KEYCTL_PROG" keyctl | 
|  |  | 
|  | # Set up an encryption-capable filesystem and an encryption key. | 
|  | _init_session_keyring | 
|  | _scratch_mkfs_encrypted &>> $seqres.full | 
|  | _scratch_mount | 
|  | keydesc=$(_generate_key_descriptor) | 
|  | raw_key=$(_generate_raw_encryption_key) | 
|  | _add_session_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_session_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_session_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_session_encryption_key $keydesc | 
|  | stat $SCRATCH_MNT/edir/file |& _filter_stat |& _filter_scratch | 
|  | cat "$(find $SCRATCH_MNT/edir/ -type f)" | 
|  | exec 3>&- | 
|  |  | 
|  | # success, all done | 
|  | status=0 | 
|  | exit |