aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-06-10 10:01:56 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-06-10 10:01:56 +0200
commit6c6a0147ce8ee79ce8176b076f7e6eb512989982 (patch)
tree4125c4d173d982441b1f878f314848e02da18b4b
parent0ce7a6b8527fbbc84add286a0efc73803a77bcab (diff)
downloadpatches-6c6a0147ce8ee79ce8176b076f7e6eb512989982.tar.gz
add readfile patches to keep "safe"
-rw-r--r--0001-readfile-implement-readfile-syscall.patch81
-rw-r--r--0002-arch-wire-up-the-readfile-syscall.patch237
-rw-r--r--0003-selftests-add-readfile-2-selftests.patch578
-rw-r--r--series3
4 files changed, 899 insertions, 0 deletions
diff --git a/0001-readfile-implement-readfile-syscall.patch b/0001-readfile-implement-readfile-syscall.patch
new file mode 100644
index 00000000000000..1393312d340858
--- /dev/null
+++ b/0001-readfile-implement-readfile-syscall.patch
@@ -0,0 +1,81 @@
+From 64793c95677d62753de4db132b0c85adab7aa9ab Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Sun, 24 May 2020 12:37:15 +0200
+Subject: [PATCH 1/3] readfile: implement readfile syscall
+
+It's a tiny syscall, meant to allow a user to do a single "open this
+file, read into this buffer, and close the file" all in a single shot.
+
+Should be good for reading "tiny" files like sysfs, procfs, and other
+"small" files.
+
+There is no restarting the syscall, this is a "simple" syscall, with the
+attempt to make reading "simple" files easier with less syscall
+overhead.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/open.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+diff --git a/fs/open.c b/fs/open.c
+index 6cd48a61cda3..9ec18cddee18 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -1370,3 +1370,53 @@ int stream_open(struct inode *inode, struct file *filp)
+ }
+
+ EXPORT_SYMBOL(stream_open);
++
++static struct file *readfile_open(int dfd, const char __user *filename,
++ struct open_flags *op)
++{
++ struct filename *tmp;
++ struct file *f;
++
++ tmp = getname(filename);
++ if (IS_ERR(tmp))
++ return (struct file *)tmp;
++
++ f = do_filp_open(dfd, tmp, op);
++ if (!IS_ERR(f))
++ fsnotify_open(f);
++
++ putname(tmp);
++ return f;
++}
++
++SYSCALL_DEFINE5(readfile, int, dfd, const char __user *, filename,
++ char __user *, buffer, size_t, bufsize, int, flags)
++{
++ struct open_flags op;
++ struct open_how how;
++ struct file *file;
++ loff_t pos = 0;
++ int retval;
++
++ /* only accept a small subset of O_ flags that make sense */
++ if ((flags | O_NOFOLLOW | O_NOATIME) != flags)
++ return -EINVAL;
++
++ /* add some needed flags to be able to open the file properly */
++ flags |= O_RDONLY | O_LARGEFILE;
++
++ how = build_open_how(flags, 0000);
++ retval = build_open_flags(&how, &op);
++ if (retval)
++ return retval;
++
++ file = readfile_open(dfd, filename, &op);
++ if (IS_ERR(file))
++ return PTR_ERR(file);
++
++ retval = vfs_read(file, buffer, bufsize, &pos);
++
++ filp_close(file, NULL);
++
++ return retval;
++}
+--
+2.27.0
+
diff --git a/0002-arch-wire-up-the-readfile-syscall.patch b/0002-arch-wire-up-the-readfile-syscall.patch
new file mode 100644
index 00000000000000..34e76f3e4c134a
--- /dev/null
+++ b/0002-arch-wire-up-the-readfile-syscall.patch
@@ -0,0 +1,237 @@
+From ef5dc99f43ca5c982c124ff6ac7acf0c1151d5bf Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Sun, 24 May 2020 12:36:21 +0200
+Subject: [PATCH 2/3] arch: wire up the readfile syscall
+
+This wires up the readfile syscall for all architectures
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/alpha/kernel/syscalls/syscall.tbl | 1 +
+ arch/arm/tools/syscall.tbl | 1 +
+ arch/arm64/include/asm/unistd.h | 2 +-
+ arch/arm64/include/asm/unistd32.h | 2 ++
+ arch/ia64/kernel/syscalls/syscall.tbl | 1 +
+ arch/m68k/kernel/syscalls/syscall.tbl | 1 +
+ arch/microblaze/kernel/syscalls/syscall.tbl | 1 +
+ arch/mips/kernel/syscalls/syscall_n32.tbl | 1 +
+ arch/mips/kernel/syscalls/syscall_n64.tbl | 1 +
+ arch/mips/kernel/syscalls/syscall_o32.tbl | 1 +
+ arch/parisc/kernel/syscalls/syscall.tbl | 1 +
+ arch/powerpc/kernel/syscalls/syscall.tbl | 1 +
+ arch/s390/kernel/syscalls/syscall.tbl | 1 +
+ arch/sh/kernel/syscalls/syscall.tbl | 1 +
+ arch/sparc/kernel/syscalls/syscall.tbl | 1 +
+ arch/x86/entry/syscalls/syscall_32.tbl | 1 +
+ arch/x86/entry/syscalls/syscall_64.tbl | 1 +
+ arch/xtensa/kernel/syscalls/syscall.tbl | 1 +
+ include/linux/syscalls.h | 2 ++
+ include/uapi/asm-generic/unistd.h | 4 +++-
+ 20 files changed, 24 insertions(+), 2 deletions(-)
+
+diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
+index 5ddd128d4b7a..4132380e997f 100644
+--- a/arch/alpha/kernel/syscalls/syscall.tbl
++++ b/arch/alpha/kernel/syscalls/syscall.tbl
+@@ -478,3 +478,4 @@
+ 547 common openat2 sys_openat2
+ 548 common pidfd_getfd sys_pidfd_getfd
+ 549 common faccessat2 sys_faccessat2
++550 common readfile sys_readfile
+diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
+index d5cae5ffede0..454873892ba3 100644
+--- a/arch/arm/tools/syscall.tbl
++++ b/arch/arm/tools/syscall.tbl
+@@ -452,3 +452,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
+index 3b859596840d..b3b2019f8d16 100644
+--- a/arch/arm64/include/asm/unistd.h
++++ b/arch/arm64/include/asm/unistd.h
+@@ -38,7 +38,7 @@
+ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5)
+ #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800)
+
+-#define __NR_compat_syscalls 440
++#define __NR_compat_syscalls 441
+ #endif
+
+ #define __ARCH_WANT_SYS_CLONE
+diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
+index 6d95d0c8bf2f..524d19779612 100644
+--- a/arch/arm64/include/asm/unistd32.h
++++ b/arch/arm64/include/asm/unistd32.h
+@@ -885,6 +885,8 @@ __SYSCALL(__NR_openat2, sys_openat2)
+ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+ #define __NR_faccessat2 439
+ __SYSCALL(__NR_faccessat2, sys_faccessat2)
++#define __NR_readfile 440
++__SYSCALL(__NR_readfile, sys_readfile)
+
+ /*
+ * Please add new compat syscalls above this comment and update
+diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl
+index 49e325b604b3..b188f03736bb 100644
+--- a/arch/ia64/kernel/syscalls/syscall.tbl
++++ b/arch/ia64/kernel/syscalls/syscall.tbl
+@@ -359,3 +359,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
+index f71b1bbcc198..ab24bcb91344 100644
+--- a/arch/m68k/kernel/syscalls/syscall.tbl
++++ b/arch/m68k/kernel/syscalls/syscall.tbl
+@@ -438,3 +438,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
+index edacc4561f2b..46c06f800e8e 100644
+--- a/arch/microblaze/kernel/syscalls/syscall.tbl
++++ b/arch/microblaze/kernel/syscalls/syscall.tbl
+@@ -444,3 +444,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
+index f777141f5256..552ba4dafbef 100644
+--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
++++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
+@@ -377,3 +377,4 @@
+ 437 n32 openat2 sys_openat2
+ 438 n32 pidfd_getfd sys_pidfd_getfd
+ 439 n32 faccessat2 sys_faccessat2
++440 n32 readfile sys_readfile
+diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
+index da8c76394e17..e12581bf900b 100644
+--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
++++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
+@@ -353,3 +353,4 @@
+ 437 n64 openat2 sys_openat2
+ 438 n64 pidfd_getfd sys_pidfd_getfd
+ 439 n64 faccessat2 sys_faccessat2
++440 n64 readfile sys_readfile
+diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
+index 13280625d312..67cb8f8fbdb2 100644
+--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
++++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
+@@ -426,3 +426,4 @@
+ 437 o32 openat2 sys_openat2
+ 438 o32 pidfd_getfd sys_pidfd_getfd
+ 439 o32 faccessat2 sys_faccessat2
++440 o32 readfile sys_readfile
+diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
+index 5a758fa6ec52..775e5228ab51 100644
+--- a/arch/parisc/kernel/syscalls/syscall.tbl
++++ b/arch/parisc/kernel/syscalls/syscall.tbl
+@@ -436,3 +436,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
+index f833a3190822..d452db708635 100644
+--- a/arch/powerpc/kernel/syscalls/syscall.tbl
++++ b/arch/powerpc/kernel/syscalls/syscall.tbl
+@@ -528,3 +528,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
+index bfdcb7633957..7ab529813a42 100644
+--- a/arch/s390/kernel/syscalls/syscall.tbl
++++ b/arch/s390/kernel/syscalls/syscall.tbl
+@@ -441,3 +441,4 @@
+ 437 common openat2 sys_openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2 sys_faccessat2
++440 common readfile sys_readfile sys_readfile
+diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
+index acc35daa1b79..ce8862cdb707 100644
+--- a/arch/sh/kernel/syscalls/syscall.tbl
++++ b/arch/sh/kernel/syscalls/syscall.tbl
+@@ -441,3 +441,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
+index 8004a276cb74..d89e7224bb0f 100644
+--- a/arch/sparc/kernel/syscalls/syscall.tbl
++++ b/arch/sparc/kernel/syscalls/syscall.tbl
+@@ -484,3 +484,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
+index d8f8a1a69ed1..6f8d0b0acb6a 100644
+--- a/arch/x86/entry/syscalls/syscall_32.tbl
++++ b/arch/x86/entry/syscalls/syscall_32.tbl
+@@ -443,3 +443,4 @@
+ 437 i386 openat2 sys_openat2
+ 438 i386 pidfd_getfd sys_pidfd_getfd
+ 439 i386 faccessat2 sys_faccessat2
++440 i386 readfile sys_readfile
+diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
+index 78847b32e137..9c54081b7c14 100644
+--- a/arch/x86/entry/syscalls/syscall_64.tbl
++++ b/arch/x86/entry/syscalls/syscall_64.tbl
+@@ -360,6 +360,7 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+
+ #
+ # x32-specific system call numbers start at 512 to avoid cache impact
+diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
+index 69d0d73876b3..7b1f2ea76621 100644
+--- a/arch/xtensa/kernel/syscalls/syscall.tbl
++++ b/arch/xtensa/kernel/syscalls/syscall.tbl
+@@ -409,3 +409,4 @@
+ 437 common openat2 sys_openat2
+ 438 common pidfd_getfd sys_pidfd_getfd
+ 439 common faccessat2 sys_faccessat2
++440 common readfile sys_readfile
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 7c354c2955f5..b5cb9425c0f4 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -1005,6 +1005,8 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
+ siginfo_t __user *info,
+ unsigned int flags);
+ asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);
++asmlinkage long sys_readfile(int dfd, const char __user *filename,
++ char __user *buffer, size_t bufsize, int flags);
+
+ /*
+ * Architecture-specific system calls
+diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
+index f4a01305d9a6..81b677c01266 100644
+--- a/include/uapi/asm-generic/unistd.h
++++ b/include/uapi/asm-generic/unistd.h
+@@ -857,9 +857,11 @@ __SYSCALL(__NR_openat2, sys_openat2)
+ __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd)
+ #define __NR_faccessat2 439
+ __SYSCALL(__NR_faccessat2, sys_faccessat2)
++#define __NR_readfile 440
++__SYSCALL(__NR_readfile, sys_readfile)
+
+ #undef __NR_syscalls
+-#define __NR_syscalls 440
++#define __NR_syscalls 441
+
+ /*
+ * 32 bit systems traditionally used different
+--
+2.27.0
+
diff --git a/0003-selftests-add-readfile-2-selftests.patch b/0003-selftests-add-readfile-2-selftests.patch
new file mode 100644
index 00000000000000..c3a405403a0e70
--- /dev/null
+++ b/0003-selftests-add-readfile-2-selftests.patch
@@ -0,0 +1,578 @@
+From 2a133d8e0cb79bc7566c39aae1191a7118a1202e Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Sun, 8 Mar 2020 09:54:45 +0100
+Subject: [PATCH 3/3] selftests: add readfile(2) selftests
+
+Test the functionality of readfile(2) in various ways.
+
+Also provide a simple speed test program to benchmark using readfile()
+instead of using open()/read()/close().
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/Makefile | 1 +
+ tools/testing/selftests/readfile/.gitignore | 3 +
+ tools/testing/selftests/readfile/Makefile | 7 +
+ tools/testing/selftests/readfile/readfile.c | 285 ++++++++++++++++++
+ .../selftests/readfile/readfile_speed.c | 221 ++++++++++++++
+ 5 files changed, 517 insertions(+)
+ create mode 100644 tools/testing/selftests/readfile/.gitignore
+ create mode 100644 tools/testing/selftests/readfile/Makefile
+ create mode 100644 tools/testing/selftests/readfile/readfile.c
+ create mode 100644 tools/testing/selftests/readfile/readfile_speed.c
+
+diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
+index 1195bd85af38..82359233b945 100644
+--- a/tools/testing/selftests/Makefile
++++ b/tools/testing/selftests/Makefile
+@@ -46,6 +46,7 @@ TARGETS += ptrace
+ TARGETS += openat2
+ TARGETS += rseq
+ TARGETS += rtc
++TARGETS += readfile
+ TARGETS += seccomp
+ TARGETS += sigaltstack
+ TARGETS += size
+diff --git a/tools/testing/selftests/readfile/.gitignore b/tools/testing/selftests/readfile/.gitignore
+new file mode 100644
+index 000000000000..f0e758d437e4
+--- /dev/null
++++ b/tools/testing/selftests/readfile/.gitignore
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++readfile
++readfile_speed
+diff --git a/tools/testing/selftests/readfile/Makefile b/tools/testing/selftests/readfile/Makefile
+new file mode 100644
+index 000000000000..1bf1bdec40f8
+--- /dev/null
++++ b/tools/testing/selftests/readfile/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0
++CFLAGS += -g -I../../../../usr/include/
++CFLAGS += -O2 -Wl,-no-as-needed -Wall
++
++TEST_GEN_PROGS := readfile readfile_speed
++
++include ../lib.mk
+diff --git a/tools/testing/selftests/readfile/readfile.c b/tools/testing/selftests/readfile/readfile.c
+new file mode 100644
+index 000000000000..f0736c6dfa69
+--- /dev/null
++++ b/tools/testing/selftests/readfile/readfile.c
+@@ -0,0 +1,285 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2020 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
++ * Copyright (c) 2020 The Linux Foundation
++ *
++ * Test the readfile() syscall in various ways.
++ */
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/syscall.h>
++#include <sys/types.h>
++#include <dirent.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <string.h>
++#include <syscall.h>
++
++#include "../kselftest.h"
++
++//#ifndef __NR_readfile
++//#define __NR_readfile -1
++//#endif
++
++#define __NR_readfile 440
++
++#define TEST_FILE1 "/sys/devices/system/cpu/vulnerabilities/meltdown"
++#define TEST_FILE2 "/sys/devices/system/cpu/vulnerabilities/spectre_v1"
++#define TEST_FILE4 "/sys/kernel/debug/usb/devices"
++
++static int sys_readfile(int fd, const char *filename, unsigned char *buffer,
++ size_t bufsize, int flags)
++{
++ return syscall(__NR_readfile, fd, filename, buffer, bufsize, flags);
++}
++
++/*
++ * Test that readfile() is even in the running kernel or not.
++ */
++static void test_readfile_supported(void)
++{
++ const char *proc_map = "/proc/self/maps";
++ unsigned char buffer[10];
++ int retval;
++
++ if (__NR_readfile < 0)
++ ksft_exit_skip("readfile() syscall is not defined for the kernel this test was built against\n");
++
++ /*
++ * Do a simple test to see if the syscall really is present in the
++ * running kernel
++ */
++ retval = sys_readfile(0, proc_map, &buffer[0], sizeof(buffer), 0);
++ if (retval == -1)
++ ksft_exit_skip("readfile() syscall not present on running kernel\n");
++
++ ksft_test_result_pass("readfile() syscall present\n");
++}
++
++/*
++ * Open all files in a specific sysfs directory and read from them
++ *
++ * This tests the "openat" type functionality of opening all files relative to a
++ * directory. We don't care at the moment about the contents.
++ */
++static void test_sysfs_files(void)
++{
++ static unsigned char buffer[8000];
++ const char *sysfs_dir = "/sys/devices/system/cpu/vulnerabilities/";
++ struct dirent *dirent;
++ DIR *vuln_sysfs_dir;
++ int sysfs_fd;
++ int retval;
++
++ sysfs_fd = open(sysfs_dir, O_PATH | O_DIRECTORY);
++ if (sysfs_fd == -1) {
++ ksft_test_result_skip("unable to open %s directory\n",
++ sysfs_dir);
++ return;
++ }
++
++ vuln_sysfs_dir = opendir(sysfs_dir);
++ if (!vuln_sysfs_dir) {
++ ksft_test_result_skip("%s unable to be opened, skipping test\n");
++ return;
++ }
++
++ ksft_print_msg("readfile: testing relative path functionality by reading files in %s\n",
++ sysfs_dir);
++ /* open all sysfs file in this directory and read the whole thing */
++ while ((dirent = readdir(vuln_sysfs_dir))) {
++ /* ignore . and .. */
++ if (strcmp(dirent->d_name, ".") == 0 ||
++ strcmp(dirent->d_name, "..") == 0)
++ continue;
++
++ retval = sys_readfile(sysfs_fd, dirent->d_name, &buffer[0],
++ sizeof(buffer), 0);
++
++ if (retval <= 0) {
++ ksft_test_result_fail("readfile(%s) failed with %d\n",
++ dirent->d_name, retval);
++ goto exit;
++ }
++
++ /* cut off trailing \n character */
++ buffer[retval - 1] = 0x00;
++ ksft_print_msg(" '%s' contains \"%s\"\n", dirent->d_name,
++ buffer);
++ }
++
++ ksft_test_result_pass("readfile() relative path functionality passed\n");
++
++exit:
++ closedir(vuln_sysfs_dir);
++ close(sysfs_fd);
++}
++
++/* Temporary directory variables */
++static int root_fd; /* test root directory file handle */
++static char tmpdir[PATH_MAX];
++
++static void setup_tmpdir(void)
++{
++ char *tmpdir_root;
++
++ tmpdir_root = getenv("TMPDIR");
++ if (!tmpdir_root)
++ tmpdir_root = "/tmp";
++
++ snprintf(tmpdir, PATH_MAX, "%s/readfile.XXXXXX", tmpdir_root);
++ if (!mkdtemp(tmpdir)) {
++ ksft_test_result_fail("mkdtemp(%s) failed\n", tmpdir);
++ ksft_exit_fail();
++ }
++
++ root_fd = open(tmpdir, O_PATH | O_DIRECTORY);
++ if (root_fd == -1) {
++ ksft_exit_fail_msg("%s unable to be opened, error = %d\n",
++ tmpdir, root_fd);
++ ksft_exit_fail();
++ }
++
++ ksft_print_msg("%s created to use for testing\n", tmpdir);
++}
++
++static void teardown_tmpdir(void)
++{
++ int retval;
++
++ close(root_fd);
++
++ retval = rmdir(tmpdir);
++ if (retval) {
++ ksft_exit_fail_msg("%s removed with return value %d\n",
++ tmpdir, retval);
++ ksft_exit_fail();
++ }
++ ksft_print_msg("%s cleaned up and removed\n", tmpdir);
++
++}
++
++static void test_filesize(size_t size)
++{
++ char filename[PATH_MAX];
++ unsigned char *write_data;
++ unsigned char *read_data;
++ int fd;
++ int retval;
++ size_t i;
++
++ snprintf(filename, PATH_MAX, "size-%ld", size);
++
++ read_data = malloc(size);
++ write_data = malloc(size);
++ if (!read_data || !write_data)
++ ksft_exit_fail_msg("Unable to allocate %ld bytes\n", size);
++
++ fd = openat(root_fd, filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
++ if (fd < 0)
++ ksft_exit_fail_msg("Unable to create file %s\n", filename);
++
++ ksft_print_msg("%s created\n", filename);
++
++ for (i = 0; i < size; ++i)
++ write_data[i] = (unsigned char)(0xff & i);
++
++ write(fd, write_data, size);
++ close(fd);
++
++ retval = sys_readfile(root_fd, filename, read_data, size, 0);
++
++ if (retval != size) {
++ ksft_test_result_fail("Read %d bytes but wanted to read %ld bytes.\n",
++ retval, size);
++ goto exit;
++ }
++
++ if (memcmp(read_data, write_data, size) != 0) {
++ ksft_test_result_fail("Read data of buffer size %d did not match written data\n",
++ size);
++ goto exit;
++ }
++
++ ksft_test_result_pass("readfile() of size %ld succeeded.\n", size);
++
++exit:
++ unlinkat(root_fd, filename, 0);
++ free(write_data);
++ free(read_data);
++}
++
++
++/*
++ * Create a bunch of differently sized files, and verify we read the correct
++ * amount of data from them.
++ */
++static void test_filesizes(void)
++{
++ setup_tmpdir();
++
++ test_filesize(0x10);
++ test_filesize(0x100);
++ test_filesize(0x1000);
++ test_filesize(0x10000);
++ test_filesize(0x100000);
++ test_filesize(0x1000000);
++
++ teardown_tmpdir();
++
++}
++
++static void readfile(const char *filename)
++{
++// int root_fd;
++ unsigned char buffer[16000];
++ int retval;
++
++ memset(buffer, 0x00, sizeof(buffer));
++
++// root_fd = open("/", O_DIRECTORY);
++// if (root_fd == -1)
++// ksft_exit_fail_msg("error with root_fd\n");
++
++ retval = sys_readfile(root_fd, filename, &buffer[0], sizeof(buffer), 0);
++
++// close(root_fd);
++
++ if (retval <= 0)
++ ksft_test_result_fail("readfile() test of filename=%s failed with retval %d\n",
++ filename, retval);
++ else
++ ksft_test_result_pass("readfile() test of filename=%s succeeded with retval=%d\n",
++ filename, retval);
++// buffer='%s'\n",
++// filename, retval, &buffer[0]);
++
++}
++
++
++int main(int argc, char *argv[])
++{
++ ksft_print_header();
++ ksft_set_plan(10);
++
++ test_readfile_supported(); // 1 test
++
++ test_sysfs_files(); // 1 test
++
++ test_filesizes(); // 6 tests
++
++ setup_tmpdir();
++
++ readfile(TEST_FILE1);
++ readfile(TEST_FILE2);
++// readfile(TEST_FILE4);
++
++ teardown_tmpdir();
++
++ if (ksft_get_fail_cnt())
++ return ksft_exit_fail();
++
++ return ksft_exit_pass();
++}
++
+diff --git a/tools/testing/selftests/readfile/readfile_speed.c b/tools/testing/selftests/readfile/readfile_speed.c
+new file mode 100644
+index 000000000000..bbf985b30d1b
+--- /dev/null
++++ b/tools/testing/selftests/readfile/readfile_speed.c
+@@ -0,0 +1,221 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2020 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
++ * Copyright (c) 2020 The Linux Foundation
++ *
++ * Tiny test program to try to benchmark the speed of the readfile syscall vs.
++ * the open/read/close sequence it replaces.
++ */
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/syscall.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <dirent.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <string.h>
++#include <syscall.h>
++#include <errno.h>
++#include <unistd.h>
++#include <stdarg.h>
++
++//#ifndef __NR_readfile
++//#define __NR_readfile -1
++//#endif
++
++#define __NR_readfile 440
++
++#define TEST_FILE "/sys/devices/system/cpu/vulnerabilities/meltdown"
++
++static int sys_readfile(int fd, const char *filename, unsigned char *buffer,
++ size_t bufsize, int flags)
++{
++ return syscall(__NR_readfile, fd, filename, buffer, bufsize, flags);
++}
++
++/* taken from all-io.h from util-linux repo */
++static inline ssize_t read_all(int fd, unsigned char *buf, size_t count)
++{
++ ssize_t ret;
++ ssize_t c = 0;
++ int tries = 0;
++
++ //memset(buf, 0, count);
++ while (count > 0) {
++ ret = read(fd, buf, count);
++ if (ret <= 0) {
++ if (ret < 0 && (errno == EAGAIN || errno == EINTR) &&
++ (tries++ < 5)) {
++ usleep(250000);
++ continue;
++ }
++ return c ? c : -1;
++ }
++ tries = 0;
++ count -= ret;
++ buf += ret;
++ c += ret;
++ }
++ return c;
++}
++
++static int openreadclose(const char *filename, unsigned char *buffer,
++ size_t bufsize)
++{
++ size_t count;
++ int fd;
++
++ fd = openat(0, filename, O_RDONLY);
++ if (fd < 0) {
++ printf("error opening %s\n", filename);
++ return fd;
++ }
++
++ count = read_all(fd, buffer, bufsize);
++ if (count < 0) {
++ printf("Error %ld reading from %s\n", count, filename);
++ }
++
++ close(fd);
++ return count;
++}
++
++enum test_type {
++ READFILE,
++ OPENREADCLOSE,
++};
++
++static int do_read_file_test(int loops, enum test_type test_type,
++ const char *filename,
++ unsigned char *buffer, size_t bufsize)
++{
++ char *test;
++ int retval;
++ int i;
++
++ switch (test_type) {
++ case READFILE:
++ test = "readfile";
++ break;
++
++ case OPENREADCLOSE:
++ test = "open/read/close";
++ break;
++ default:
++ fprintf(stderr, "wrong test type");
++ return -1;
++ }
++
++ fprintf(stdout,
++ "Running %s test on file %s for %d loops...\n",
++ test, filename, loops);
++
++ for (i = 0; i < loops; ++i) {
++ switch (test_type) {
++ case READFILE:
++ retval = sys_readfile(0, filename, buffer, bufsize, O_RDONLY);
++ break;
++
++ case OPENREADCLOSE:
++ retval = openreadclose(filename, buffer, bufsize);
++ break;
++ }
++ if (retval < 0) {
++ fprintf(stderr,
++ "test failed on loop %d with error %d\n",
++ i, retval);
++ return retval;
++ }
++ }
++ return 0;
++}
++
++static int check_file_present(const char *filename)
++{
++ struct stat sb;
++ int retval;
++
++ retval = stat(filename, &sb);
++ if (retval == -1) {
++ fprintf(stderr,
++ "filename %s is not present\n", filename);
++ return retval;
++ }
++
++ if ((sb.st_mode & S_IFMT) != S_IFREG) {
++ fprintf(stderr,
++ "filename %s must be a real file, not anything else.\n",
++ filename);
++ return -1;
++ }
++ return 0;
++}
++
++static void usage(char *progname)
++{
++ fprintf(stderr,
++ "usage: %s [options]\n"
++ " -l loops Number of loops to run the test for.\n"
++ " default is 10'000\n"
++ " -t testtype Test type to run\n"
++ " types are: readfile, openreadclose\n"
++ " default is readfile\n",
++ progname);
++}
++
++int main(int argc, char *argv[])
++{
++ int loops = 10000;
++ unsigned char buffer[10000];
++ char c;
++ char *testtype = "readfile";
++ char *progname;
++ char *filename;
++ enum test_type test_type;
++ int retval;
++
++ progname = strrchr(argv[0], '/');
++ progname = progname ? 1+progname : argv[0];
++
++ while (EOF != (c = getopt(argc, argv, "t:hl:"))) {
++ switch (c) {
++ case 'l':
++ loops = atoi(optarg);
++ break;
++
++ case 't':
++ testtype = optarg;
++ break;
++
++ case 'h':
++ usage(progname);
++ return 0;
++
++ default:
++ usage(progname);
++ return -1;
++ }
++ }
++
++ if (strcmp(testtype, "readfile") == 0)
++ test_type = READFILE;
++ else if (strcmp(testtype, "openreadclose") == 0)
++ test_type = OPENREADCLOSE;
++ else {
++ usage(progname);
++ return -1;
++ }
++
++ filename = TEST_FILE;
++
++ retval = check_file_present(filename);
++ if (retval)
++ return retval;
++
++ retval = do_read_file_test(loops, test_type, TEST_FILE,
++ &buffer[0], sizeof(buffer));
++
++ return retval;
++}
+--
+2.27.0
+
diff --git a/series b/series
index b109a2ebbb97e3..b8f0b8c93ed662 100644
--- a/series
+++ b/series
@@ -1,4 +1,7 @@
#
+0001-readfile-implement-readfile-syscall.patch
+0002-arch-wire-up-the-readfile-syscall.patch
+0003-selftests-add-readfile-2-selftests.patch
spdxcheck-print-out-files-without-any-spdx-lines.patch
0001-tty-n_r3964-locking-fixups.patch