Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: splice: Check behavior of full and short splices

In order to help catch regressions in splice vs read behavior in certain
special files, test a few with various different kinds of internal
kernel helpers.

Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>

+118 -2
+1
tools/testing/selftests/splice/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 default_file_splice_read 3 + splice_read
+2 -2
tools/testing/selftests/splice/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - TEST_PROGS := default_file_splice_read.sh 3 - TEST_GEN_PROGS_EXTENDED := default_file_splice_read 2 + TEST_PROGS := default_file_splice_read.sh short_splice_read.sh 3 + TEST_GEN_PROGS_EXTENDED := default_file_splice_read splice_read 4 4 5 5 include ../lib.mk
+1
tools/testing/selftests/splice/config
··· 1 + CONFIG_TEST_LKM=m
+1
tools/testing/selftests/splice/settings
··· 1 + timeout=5
+56
tools/testing/selftests/splice/short_splice_read.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + set -e 4 + 5 + ret=0 6 + 7 + do_splice() 8 + { 9 + filename="$1" 10 + bytes="$2" 11 + expected="$3" 12 + 13 + out=$(./splice_read "$filename" "$bytes" | cat) 14 + if [ "$out" = "$expected" ] ; then 15 + echo "ok: $filename $bytes" 16 + else 17 + echo "FAIL: $filename $bytes" 18 + ret=1 19 + fi 20 + } 21 + 22 + test_splice() 23 + { 24 + filename="$1" 25 + 26 + full=$(cat "$filename") 27 + two=$(echo "$full" | grep -m1 . | cut -c-2) 28 + 29 + # Make sure full splice has the same contents as a standard read. 30 + do_splice "$filename" 4096 "$full" 31 + 32 + # Make sure a partial splice see the first two characters. 33 + do_splice "$filename" 2 "$two" 34 + } 35 + 36 + # proc_single_open(), seq_read() 37 + test_splice /proc/$$/limits 38 + # special open, seq_read() 39 + test_splice /proc/$$/comm 40 + 41 + # proc_handler, proc_dointvec_minmax 42 + test_splice /proc/sys/fs/nr_open 43 + # proc_handler, proc_dostring 44 + test_splice /proc/sys/kernel/modprobe 45 + # proc_handler, special read 46 + test_splice /proc/sys/kernel/version 47 + 48 + if ! [ -d /sys/module/test_module/sections ] ; then 49 + modprobe test_module 50 + fi 51 + # kernfs, attr 52 + test_splice /sys/module/test_module/coresize 53 + # kernfs, binattr 54 + test_splice /sys/module/test_module/sections/.init.text 55 + 56 + exit $ret
+57
tools/testing/selftests/splice/splice_read.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #define _GNU_SOURCE 3 + #include <errno.h> 4 + #include <fcntl.h> 5 + #include <limits.h> 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + #include <unistd.h> 9 + #include <sys/types.h> 10 + #include <sys/stat.h> 11 + 12 + int main(int argc, char *argv[]) 13 + { 14 + int fd; 15 + size_t size; 16 + ssize_t spliced; 17 + 18 + if (argc < 2) { 19 + fprintf(stderr, "Usage: %s INPUT [BYTES]\n", argv[0]); 20 + return EXIT_FAILURE; 21 + } 22 + 23 + fd = open(argv[1], O_RDONLY); 24 + if (fd < 0) { 25 + perror(argv[1]); 26 + return EXIT_FAILURE; 27 + } 28 + 29 + if (argc == 3) 30 + size = atol(argv[2]); 31 + else { 32 + struct stat statbuf; 33 + 34 + if (fstat(fd, &statbuf) < 0) { 35 + perror(argv[1]); 36 + return EXIT_FAILURE; 37 + } 38 + 39 + if (statbuf.st_size > INT_MAX) { 40 + fprintf(stderr, "%s: Too big\n", argv[1]); 41 + return EXIT_FAILURE; 42 + } 43 + 44 + size = statbuf.st_size; 45 + } 46 + 47 + /* splice(2) file to stdout. */ 48 + spliced = splice(fd, NULL, STDOUT_FILENO, NULL, 49 + size, SPLICE_F_MOVE); 50 + if (spliced < 0) { 51 + perror("splice"); 52 + return EXIT_FAILURE; 53 + } 54 + 55 + close(fd); 56 + return EXIT_SUCCESS; 57 + }