-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests: splice: Adjust for handler fallback removal
[ Upstream commit 6daf076 ] Some pseudo-filesystems do not have an explicit splice fops since adding commit 36e2c74 ("fs: don't allow splice read/write without explicit ops"), and now will reject attempts to use splice() in those filesystem paths. Reported-by: kernel test robot <rong.a.chen@intel.com> Link: https://lore.kernel.org/lkml/202009181443.C2179FB@keescook/ Fixes: 36e2c74 ("fs: don't allow splice read/write without explicit ops") Cc: Christoph Hellwig <hch@lst.de> Cc: Shuah Khan <shuah@kernel.org> Cc: linux-kselftest@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
- Loading branch information
Showing
1 changed file
with
98 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,133 @@ | ||
#!/bin/sh | ||
# SPDX-License-Identifier: GPL-2.0 | ||
# | ||
# Test for mishandling of splice() on pseudofilesystems, which should catch | ||
# bugs like 11990a5bd7e5 ("module: Correctly truncate sysfs sections output") | ||
# | ||
# Since splice fallback was removed as part of the set_fs() rework, many of these | ||
# tests expect to fail now. See https://lore.kernel.org/lkml/202009181443.C2179FB@keescook/ | ||
set -e | ||
|
||
DIR=$(dirname "$0") | ||
|
||
ret=0 | ||
|
||
expect_success() | ||
{ | ||
title="$1" | ||
shift | ||
|
||
echo "" >&2 | ||
echo "$title ..." >&2 | ||
|
||
set +e | ||
"$@" | ||
rc=$? | ||
set -e | ||
|
||
case "$rc" in | ||
0) | ||
echo "ok: $title succeeded" >&2 | ||
;; | ||
1) | ||
echo "FAIL: $title should work" >&2 | ||
ret=$(( ret + 1 )) | ||
;; | ||
*) | ||
echo "FAIL: something else went wrong" >&2 | ||
ret=$(( ret + 1 )) | ||
;; | ||
esac | ||
} | ||
|
||
expect_failure() | ||
{ | ||
title="$1" | ||
shift | ||
|
||
echo "" >&2 | ||
echo "$title ..." >&2 | ||
|
||
set +e | ||
"$@" | ||
rc=$? | ||
set -e | ||
|
||
case "$rc" in | ||
0) | ||
echo "FAIL: $title unexpectedly worked" >&2 | ||
ret=$(( ret + 1 )) | ||
;; | ||
1) | ||
echo "ok: $title correctly failed" >&2 | ||
;; | ||
*) | ||
echo "FAIL: something else went wrong" >&2 | ||
ret=$(( ret + 1 )) | ||
;; | ||
esac | ||
} | ||
|
||
do_splice() | ||
{ | ||
filename="$1" | ||
bytes="$2" | ||
expected="$3" | ||
report="$4" | ||
|
||
out=$(./splice_read "$filename" "$bytes" | cat) | ||
out=$("$DIR"/splice_read "$filename" "$bytes" | cat) | ||
if [ "$out" = "$expected" ] ; then | ||
echo "ok: $filename $bytes" | ||
echo " matched $report" >&2 | ||
return 0 | ||
else | ||
echo "FAIL: $filename $bytes" | ||
ret=1 | ||
echo " no match: '$out' vs $report" >&2 | ||
return 1 | ||
fi | ||
} | ||
|
||
test_splice() | ||
{ | ||
filename="$1" | ||
|
||
echo " checking $filename ..." >&2 | ||
|
||
full=$(cat "$filename") | ||
rc=$? | ||
if [ $rc -ne 0 ] ; then | ||
return 2 | ||
fi | ||
|
||
two=$(echo "$full" | grep -m1 . | cut -c-2) | ||
|
||
# Make sure full splice has the same contents as a standard read. | ||
do_splice "$filename" 4096 "$full" | ||
echo " splicing 4096 bytes ..." >&2 | ||
if ! do_splice "$filename" 4096 "$full" "full read" ; then | ||
return 1 | ||
fi | ||
|
||
# Make sure a partial splice see the first two characters. | ||
do_splice "$filename" 2 "$two" | ||
echo " splicing 2 bytes ..." >&2 | ||
if ! do_splice "$filename" 2 "$two" "'$two'" ; then | ||
return 1 | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
# proc_single_open(), seq_read() | ||
test_splice /proc/$$/limits | ||
# special open, seq_read() | ||
test_splice /proc/$$/comm | ||
### /proc/$pid/ has no splice interface; these should all fail. | ||
expect_failure "proc_single_open(), seq_read() splice" test_splice /proc/$$/limits | ||
expect_failure "special open(), seq_read() splice" test_splice /proc/$$/comm | ||
|
||
# proc_handler, proc_dointvec_minmax | ||
test_splice /proc/sys/fs/nr_open | ||
# proc_handler, proc_dostring | ||
test_splice /proc/sys/kernel/modprobe | ||
# proc_handler, special read | ||
test_splice /proc/sys/kernel/version | ||
### /proc/sys/ has a splice interface; these should all succeed. | ||
expect_success "proc_handler: proc_dointvec_minmax() splice" test_splice /proc/sys/fs/nr_open | ||
expect_success "proc_handler: proc_dostring() splice" test_splice /proc/sys/kernel/modprobe | ||
expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/version | ||
|
||
### /sys/ has no splice interface; these should all fail. | ||
if ! [ -d /sys/module/test_module/sections ] ; then | ||
modprobe test_module | ||
expect_success "test_module kernel module load" modprobe test_module | ||
fi | ||
# kernfs, attr | ||
test_splice /sys/module/test_module/coresize | ||
# kernfs, binattr | ||
test_splice /sys/module/test_module/sections/.init.text | ||
expect_failure "kernfs attr splice" test_splice /sys/module/test_module/coresize | ||
expect_failure "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text | ||
|
||
exit $ret |