mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
9bcb266cd7
If generic/397 is executed in an environment with SIGPIPE ignored,
it fails because the 'yes' program prints an error message:
yes: standard output: Broken pipe
yes: write error
This can be reproduced with:
trap '' SIGPIPE; ./check generic/397
Fix it by generating the string of 255 y's using just 'head' and
'tr' instead of 'yes', 'head', and 'tr'.
Although it's not really a good idea to execute xfstests with
SIGPIPE ignored, this is the only test I've noticed where it causes
a problem, so it might as well be fixed in the test.
It would be much nicer to prevent this problem for all tests by
making the 'check' script restore the default SIGPIPE handler. But
that isn't straightforward because bash's 'trap' builtin doesn't
allow un-ignoring signals that were ignored on entry to the shell.
[ eguan added more background infomation to commit log, which is
also from Eric.
I think it's an easy problem for others to run into, since sometimes
processes ignore SIGPIPE because they want to get write errors
instead, but then when doing fork() + exec() they forget to reset
the SIGPIPE handler. Notably, Python got this wrong and it wasn't
fixed until Python 3, so any programs executing the 'check' script
from a Python 2 script will usually get this wrong (see:
https://bugs.python.org/issue1652). And usually everything works
fine but every once in a while there is a weird problem like this
which has to be debugged. ]
Signed-off-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Eryu Guan <eguan@redhat.com>
Signed-off-by: Eryu Guan <eguan@redhat.com>
145 lines
5.3 KiB
Bash
Executable File
145 lines
5.3 KiB
Bash
Executable File
#! /bin/bash
|
|
# FS QA Test generic/397
|
|
#
|
|
# Test accessing encrypted files and directories, both with and without the
|
|
# encryption key. Access with the encryption key is more of a sanity check and
|
|
# is not intended to fully test all the encrypted I/O paths; to do that you'd
|
|
# need to run all the xfstests with encryption enabled. Access without the
|
|
# encryption key, on the other hand, should result in some particular behaviors.
|
|
#
|
|
#-----------------------------------------------------------------------
|
|
# Copyright (c) 2016 Google, Inc. All Rights Reserved.
|
|
#
|
|
# Author: Eric Biggers <ebiggers@google.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it would be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write the Free Software Foundation,
|
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
#-----------------------------------------------------------------------
|
|
#
|
|
|
|
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_xfs_io_command "set_encpolicy"
|
|
_require_command "$KEYCTL_PROG" keyctl
|
|
|
|
_new_session_keyring
|
|
|
|
_scratch_mkfs_encrypted &>> $seqres.full
|
|
_scratch_mount
|
|
|
|
mkdir $SCRATCH_MNT/edir $SCRATCH_MNT/ref_dir
|
|
keydesc=$(_generate_encryption_key)
|
|
$XFS_IO_PROG -c "set_encpolicy $keydesc" $SCRATCH_MNT/edir
|
|
for dir in $SCRATCH_MNT/edir $SCRATCH_MNT/ref_dir; do
|
|
touch $dir/empty > /dev/null
|
|
$XFS_IO_PROG -t -f -c "pwrite 0 4k" $dir/a > /dev/null
|
|
$XFS_IO_PROG -t -f -c "pwrite 0 33k" $dir/abcdefghijklmnopqrstuvwxyz > /dev/null
|
|
maxname=$(head -c 255 /dev/zero | tr '\0' y) # 255 character filename
|
|
$XFS_IO_PROG -t -f -c "pwrite 0 1k" $dir/$maxname > /dev/null
|
|
ln -s a $dir/symlink
|
|
ln -s abcdefghijklmnopqrstuvwxyz $dir/symlink2
|
|
ln -s $maxname $dir/symlink3
|
|
mkdir $dir/subdir
|
|
mkdir $dir/subdir/subsubdir
|
|
done
|
|
# Diff encrypted directory with unencrypted reference directory
|
|
diff -r $SCRATCH_MNT/edir $SCRATCH_MNT/ref_dir
|
|
# Cycle mount and diff again
|
|
_scratch_cycle_mount
|
|
diff -r $SCRATCH_MNT/edir $SCRATCH_MNT/ref_dir
|
|
|
|
#
|
|
# Now try accessing the files without the encryption key. It should still be
|
|
# possible to list the directory and remove files. But filenames should be
|
|
# encrypted, and it should not be possible to read regular files or to create
|
|
# new files or subdirectories.
|
|
#
|
|
# Note that we cannot simply use ls -R to verify the files because the encrypted
|
|
# filenames are unpredictable. By design, the key used to encrypt a directory's
|
|
# filenames is derived from the master key (the key in the keyring) and a nonce
|
|
# generated by the kernel. Hence, the encrypted filenames will be different
|
|
# every time this test is run, even if we were to put a fixed key into the
|
|
# keyring instead of a random one. The same applies to symlink targets.
|
|
#
|
|
# TODO: there are some inconsistencies in which error codes are returned on
|
|
# different kernel versions and filesystems when trying to create a file or
|
|
# subdirectory without access to the parent directory's encryption key. It's
|
|
# planned to consistently use ENOKEY, but for now make this test accept multiple
|
|
# error codes...
|
|
#
|
|
|
|
filter_create_errors()
|
|
{
|
|
sed -e 's/No such file or directory/Required key not available/' \
|
|
-e 's/Permission denied/Required key not available/' \
|
|
-e 's/Operation not permitted/Required key not available/'
|
|
}
|
|
|
|
_unlink_encryption_key $keydesc
|
|
_scratch_cycle_mount
|
|
|
|
# Check that unencrypted names aren't there
|
|
stat $SCRATCH_MNT/edir/empty |& _filter_scratch
|
|
stat $SCRATCH_MNT/edir/symlink |& _filter_scratch
|
|
|
|
# Check that the correct numbers of files and subdirectories are there
|
|
ls $SCRATCH_MNT/edir | wc -l
|
|
find $SCRATCH_MNT/edir -mindepth 2 -maxdepth 2 -type d | wc -l
|
|
|
|
# Try to read a nondirectory file (should fail with ENOKEY)
|
|
md5sum $(find $SCRATCH_MNT/edir -maxdepth 1 -type f | head -1) |& \
|
|
cut -d ' ' -f3-
|
|
|
|
# Try to create new files, directories, and symlinks in the encrypted directory,
|
|
# both with and without using correctly base-64 encoded filenames. These should
|
|
# all fail with ENOKEY.
|
|
$XFS_IO_PROG -f $SCRATCH_MNT/edir/newfile |& filter_create_errors | _filter_scratch
|
|
$XFS_IO_PROG -f $SCRATCH_MNT/edir/0123456789abcdef |& filter_create_errors | _filter_scratch
|
|
mkdir $SCRATCH_MNT/edir/newdir |& filter_create_errors | _filter_scratch
|
|
mkdir $SCRATCH_MNT/edir/0123456789abcdef |& filter_create_errors | _filter_scratch
|
|
ln -s foo $SCRATCH_MNT/edir/newlink |& filter_create_errors | _filter_scratch
|
|
ln -s foo $SCRATCH_MNT/edir/0123456789abcdef |& filter_create_errors | _filter_scratch
|
|
|
|
# Delete the encrypted directory (should succeed)
|
|
rm -r $SCRATCH_MNT/edir
|
|
stat $SCRATCH_MNT/edir |& _filter_scratch
|
|
|
|
# success, all done
|
|
status=0
|
|
exit
|