blob: d559e3bbdb7ba44bba6fddef92645172f07c6d9f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright 2020 Google LLC
#
# FS QA Test No. 595
#
# Regression test for a bug in the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl fixed by
# commit 2b4eae95c736 ("fscrypt: don't evict dirty inodes after removing key").
# This bug could cause writes to encrypted files to be lost if they raced with
# the corresponding fscrypt master key being removed. With f2fs, this bug could
# also crash the kernel.
#
. ./common/preamble
_begin_fstest auto quick encrypt
# Override the default cleanup function.
_cleanup()
{
# Stop all subprocesses.
touch $tmp.done
wait
rm -f $tmp.*
}
# Import common functions.
. ./common/filter
. ./common/encrypt
# real QA test starts here
_supported_fs generic
_require_scratch_encryption -v 2
_require_command "$KEYCTL_PROG" keyctl
_scratch_mkfs_encrypted &>> $seqres.full
_scratch_mount
dir=$SCRATCH_MNT/dir
runtime=$((4 * TIME_FACTOR))
# Create an encrypted directory.
mkdir $dir
_set_encpolicy $dir $TEST_KEY_IDENTIFIER
_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY"
# Start with a single-threaded reproducer:
echo -e "\n# Single-threaded reproducer"
# Keep a fd open to a file past its fscrypt master key being removed.
exec 3>$dir/file
_rm_enckey $SCRATCH_MNT $TEST_KEY_IDENTIFIER
# Write to and close the open fd.
echo contents >&3
exec 3>&-
# Drop any dentries which might be pinning the inode for "file".
echo 2 > /proc/sys/vm/drop_caches
# In buggy kernels, the inode for "file" was evicted despite the dirty data,
# causing the dirty data to be lost. Check whether the write made it through.
_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY"
cat $dir/file
rm -f $dir/file
# Also run a multi-threaded reproducer. This is included for good measure, as
# this type of thing tends to be good for finding other bugs too.
echo -e "\n# Multi-threaded reproducer"
touch $dir/file
# One process add/removes the encryption key repeatedly.
(
while [ ! -e $tmp.done ]; do
_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" > /dev/null
_rm_enckey $SCRATCH_MNT $TEST_KEY_IDENTIFIER &> /dev/null
done
) &
# Another process repeatedly tries to append to the encrypted file. The file is
# re-opened each time, so that there are chances for the inode to be evicted.
# Failures to open the file due to the key being removed are ignored.
(
touch $tmp.expected
while [ ! -e $tmp.done ]; do
if sh -c "echo -n X >> $dir/file" 2>/dev/null; then
# Keep track of the expected file contents.
echo -n X >> $tmp.expected
fi
done
) &
# Run for a while.
sleep $runtime
# Stop all subprocesses.
touch $tmp.done
wait
# Make sure no writes were lost.
_add_enckey $SCRATCH_MNT "$TEST_RAW_KEY" > /dev/null
stat $tmp.expected >> $seqres.full
stat $dir/file >> $seqres.full
cmp $tmp.expected $dir/file
echo "Multi-threaded reproducer done"
# success, all done
status=0
exit
|