mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
1c5c2aa7f6
generic/581 passes for me, but Murphy Zhou reported that it started
failing for him. The part that failed is the part that sets the key
quota to the fsgqa user's current number of keys plus 5, then tries to
add 6 filesystem encryption keys as the fsgqa user. Adding the 6th key
unexpectedly succeeded.
What I think is happening is that because the kernel's keys subsystem
garbage-collects keys asynchronously, the quota may be freed up later
than expected after removing fscrypt keys. Thus the test is flaky.
It would be nice to fix this in the kernel, but unfortunately there
doesn't seem to be an easy fix, and the keys subsystem has always worked
this way. And it seems unlikely to cause real-world problems, as the
keys quota really just exists to prevent denial-of-service attacks.
So, for now just try to make the test more reliable by:
(1) Reduce the scope of the modified keys quota to just the part of the
test that needs it.
(2) Before getting the current number of keys for the purpose of setting
the quota, wait for any invalidated keys to be garbage-collected.
Tested with a kernel that has a 1 second sleep hacked into the beginning
of key_garbage_collector(). With that, this test fails before this
patch and passes afterwards.
Reported-by: Murphy Zhou <xzhou@redhat.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
Acked-by: Murphy Zhou <xzhou@redhat.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
158 lines
4.4 KiB
Bash
Executable File
158 lines
4.4 KiB
Bash
Executable File
#! /bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
# Copyright 2019 Google LLC
|
|
#
|
|
# FS QA Test No. generic/581
|
|
#
|
|
# Test non-root use of the fscrypt filesystem-level encryption keyring
|
|
# and v2 encryption policies.
|
|
#
|
|
|
|
seq=`basename $0`
|
|
seqres=$RESULT_DIR/$seq
|
|
echo "QA output created by $seq"
|
|
echo
|
|
|
|
here=`pwd`
|
|
tmp=/tmp/$$
|
|
status=1 # failure is the default!
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
orig_maxkeys=
|
|
|
|
_cleanup()
|
|
{
|
|
cd /
|
|
rm -f $tmp.*
|
|
if [ -n "$orig_maxkeys" ]; then
|
|
echo "$orig_maxkeys" > /proc/sys/kernel/keys/maxkeys
|
|
fi
|
|
}
|
|
|
|
# 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_user
|
|
_require_scratch_encryption -v 2
|
|
|
|
_scratch_mkfs_encrypted &>> $seqres.full
|
|
_scratch_mount
|
|
|
|
dir=$SCRATCH_MNT/dir
|
|
|
|
raw_key=""
|
|
for i in `seq 64`; do
|
|
raw_key+="\\x$(printf "%02x" $i)"
|
|
done
|
|
keydesc="0000111122223333"
|
|
keyid="69b2f6edeee720cce0577937eb8a6751"
|
|
chmod 777 $SCRATCH_MNT
|
|
|
|
_user_do "mkdir $dir"
|
|
|
|
echo "# Setting v1 policy as regular user (should succeed)"
|
|
_user_do_set_encpolicy $dir $keydesc
|
|
|
|
echo "# Getting v1 policy as regular user (should succeed)"
|
|
_user_do_get_encpolicy $dir | _filter_scratch
|
|
|
|
echo "# Adding v1 policy key as regular user (should fail with EACCES)"
|
|
_user_do_add_enckey $SCRATCH_MNT "$raw_key" -d $keydesc
|
|
|
|
rm -rf $dir
|
|
echo
|
|
_user_do "mkdir $dir"
|
|
|
|
echo "# Setting v2 policy as regular user without key already added (should fail with ENOKEY)"
|
|
_user_do_set_encpolicy $dir $keyid |& _filter_scratch
|
|
|
|
echo "# Adding v2 policy key as regular user (should succeed)"
|
|
_user_do_add_enckey $SCRATCH_MNT "$raw_key"
|
|
|
|
echo "# Setting v2 policy as regular user with key added (should succeed)"
|
|
_user_do_set_encpolicy $dir $keyid
|
|
|
|
echo "# Getting v2 policy as regular user (should succeed)"
|
|
_user_do_get_encpolicy $dir | _filter_scratch
|
|
|
|
echo "# Creating encrypted file as regular user (should succeed)"
|
|
_user_do "echo contents > $dir/file"
|
|
|
|
echo "# Removing v2 policy key as regular user (should succeed)"
|
|
_user_do_rm_enckey $SCRATCH_MNT $keyid
|
|
|
|
_scratch_cycle_mount # Clear all keys
|
|
|
|
# Wait for any invalidated keys to be garbage-collected.
|
|
i=0
|
|
while grep -E -q '^[0-9a-f]+ [^ ]*i[^ ]*' /proc/keys; do
|
|
if ((++i >= 20)); then
|
|
echo "Timed out waiting for invalidated keys to be GC'ed" >> $seqres.full
|
|
break
|
|
fi
|
|
sleep 0.5
|
|
done
|
|
|
|
# Set the user key quota to the fsgqa user's current number of keys plus 5.
|
|
orig_keys=$(_user_do "awk '/^[[:space:]]*$(id -u fsgqa):/{print \$4}' /proc/key-users | cut -d/ -f1")
|
|
: ${orig_keys:=0}
|
|
echo "orig_keys=$orig_keys" >> $seqres.full
|
|
orig_maxkeys=$(</proc/sys/kernel/keys/maxkeys)
|
|
keys_to_add=5
|
|
echo $((orig_keys + keys_to_add)) > /proc/sys/kernel/keys/maxkeys
|
|
|
|
echo
|
|
echo "# Testing user key quota"
|
|
for i in `seq $((keys_to_add + 1))`; do
|
|
rand_raw_key=$(_generate_raw_encryption_key)
|
|
_user_do_add_enckey $SCRATCH_MNT "$rand_raw_key" \
|
|
| sed 's/ with identifier .*$//'
|
|
done
|
|
|
|
# Restore the original key quota.
|
|
echo "$orig_maxkeys" > /proc/sys/kernel/keys/maxkeys
|
|
|
|
rm -rf $dir
|
|
echo
|
|
_user_do "mkdir $dir"
|
|
_scratch_cycle_mount # Clear all keys
|
|
|
|
# Test multiple users adding the same key.
|
|
echo "# Adding key as root"
|
|
_add_enckey $SCRATCH_MNT "$raw_key"
|
|
echo "# Getting key status as regular user"
|
|
_user_do_enckey_status $SCRATCH_MNT $keyid
|
|
echo "# Removing key only added by another user (should fail with ENOKEY)"
|
|
_user_do_rm_enckey $SCRATCH_MNT $keyid
|
|
echo "# Setting v2 encryption policy with key only added by another user (should fail with ENOKEY)"
|
|
_user_do_set_encpolicy $dir $keyid |& _filter_scratch
|
|
echo "# Adding second user of key"
|
|
_user_do_add_enckey $SCRATCH_MNT "$raw_key"
|
|
echo "# Getting key status as regular user"
|
|
_user_do_enckey_status $SCRATCH_MNT $keyid
|
|
echo "# Setting v2 encryption policy as regular user"
|
|
_user_do_set_encpolicy $dir $keyid
|
|
echo "# Removing this user's claim to the key"
|
|
_user_do_rm_enckey $SCRATCH_MNT $keyid
|
|
echo "# Getting key status as regular user"
|
|
_user_do_enckey_status $SCRATCH_MNT $keyid
|
|
echo "# Adding back second user of key"
|
|
_user_do_add_enckey $SCRATCH_MNT "$raw_key"
|
|
echo "# Remove key for \"all users\", as regular user (should fail with EACCES)"
|
|
_user_do_rm_enckey $SCRATCH_MNT $keyid -a |& _filter_scratch
|
|
_enckey_status $SCRATCH_MNT $keyid
|
|
echo "# Remove key for \"all users\", as root"
|
|
_rm_enckey $SCRATCH_MNT $keyid -a
|
|
_enckey_status $SCRATCH_MNT $keyid
|
|
|
|
# success, all done
|
|
status=0
|
|
exit
|