| #! /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 |