Skip to content

Commit

Permalink
selftests: splice: Check behavior of full and short splices
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kees Cook committed Aug 7, 2020
1 parent 11990a5 commit 9af4766
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 2 deletions.
1 change: 1 addition & 0 deletions tools/testing/selftests/splice/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
default_file_splice_read
splice_read
4 changes: 2 additions & 2 deletions tools/testing/selftests/splice/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
TEST_PROGS := default_file_splice_read.sh
TEST_GEN_PROGS_EXTENDED := default_file_splice_read
TEST_PROGS := default_file_splice_read.sh short_splice_read.sh
TEST_GEN_PROGS_EXTENDED := default_file_splice_read splice_read

include ../lib.mk
1 change: 1 addition & 0 deletions tools/testing/selftests/splice/config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_TEST_LKM=m
1 change: 1 addition & 0 deletions tools/testing/selftests/splice/settings
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
timeout=5
56 changes: 56 additions & 0 deletions tools/testing/selftests/splice/short_splice_read.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
set -e

ret=0

do_splice()
{
filename="$1"
bytes="$2"
expected="$3"

out=$(./splice_read "$filename" "$bytes" | cat)
if [ "$out" = "$expected" ] ; then
echo "ok: $filename $bytes"
else
echo "FAIL: $filename $bytes"
ret=1
fi
}

test_splice()
{
filename="$1"

full=$(cat "$filename")
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"

# Make sure a partial splice see the first two characters.
do_splice "$filename" 2 "$two"
}

# proc_single_open(), seq_read()
test_splice /proc/$$/limits
# special open, seq_read()
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

if ! [ -d /sys/module/test_module/sections ] ; then
modprobe test_module
fi
# kernfs, attr
test_splice /sys/module/test_module/coresize
# kernfs, binattr
test_splice /sys/module/test_module/sections/.init.text

exit $ret
57 changes: 57 additions & 0 deletions tools/testing/selftests/splice/splice_read.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
int fd;
size_t size;
ssize_t spliced;

if (argc < 2) {
fprintf(stderr, "Usage: %s INPUT [BYTES]\n", argv[0]);
return EXIT_FAILURE;
}

fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror(argv[1]);
return EXIT_FAILURE;
}

if (argc == 3)
size = atol(argv[2]);
else {
struct stat statbuf;

if (fstat(fd, &statbuf) < 0) {
perror(argv[1]);
return EXIT_FAILURE;
}

if (statbuf.st_size > INT_MAX) {
fprintf(stderr, "%s: Too big\n", argv[1]);
return EXIT_FAILURE;
}

size = statbuf.st_size;
}

/* splice(2) file to stdout. */
spliced = splice(fd, NULL, STDOUT_FILENO, NULL,
size, SPLICE_F_MOVE);
if (spliced < 0) {
perror("splice");
return EXIT_FAILURE;
}

close(fd);
return EXIT_SUCCESS;
}

0 comments on commit 9af4766

Please sign in to comment.