* [PATCH 0/2] module: Correctly truncate sysfs sections output @ 2020-08-07 6:35 Kees Cook 2020-08-07 6:35 ` [PATCH 1/2] " Kees Cook 2020-08-07 6:35 ` [PATCH 2/2] selftests: splice: Check behavior of full and short splices Kees Cook 0 siblings, 2 replies; 5+ messages in thread From: Kees Cook @ 2020-08-07 6:35 UTC (permalink / raw) To: linux-kernel Cc: Kees Cook, Jessica Yu, Shuah Khan, Greg Kroah-Hartman, Masahiro Yamada, linux-kselftest Hi, This fixes my sysfs module sections refactoring to take into account the case where the output buffer is not PAGE_SIZE. :( Thanks to 0day and trinity for noticing. I'll let this sit in -next for a few days and then send it to Linus. -Kees Kees Cook (2): module: Correctly truncate sysfs sections output selftests: splice: Check behavior of full and short splices kernel/module.c | 22 ++++++- tools/testing/selftests/splice/.gitignore | 1 + tools/testing/selftests/splice/Makefile | 4 +- tools/testing/selftests/splice/config | 1 + tools/testing/selftests/splice/settings | 1 + .../selftests/splice/short_splice_read.sh | 56 ++++++++++++++++++ tools/testing/selftests/splice/splice_read.c | 57 +++++++++++++++++++ 7 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 tools/testing/selftests/splice/config create mode 100644 tools/testing/selftests/splice/settings create mode 100755 tools/testing/selftests/splice/short_splice_read.sh create mode 100644 tools/testing/selftests/splice/splice_read.c -- 2.25.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] module: Correctly truncate sysfs sections output 2020-08-07 6:35 [PATCH 0/2] module: Correctly truncate sysfs sections output Kees Cook @ 2020-08-07 6:35 ` Kees Cook 2020-08-07 6:47 ` Greg Kroah-Hartman 2020-08-07 13:18 ` Jessica Yu 2020-08-07 6:35 ` [PATCH 2/2] selftests: splice: Check behavior of full and short splices Kees Cook 1 sibling, 2 replies; 5+ messages in thread From: Kees Cook @ 2020-08-07 6:35 UTC (permalink / raw) To: linux-kernel Cc: Kees Cook, kernel test robot, stable, Jessica Yu, Shuah Khan, Greg Kroah-Hartman, Masahiro Yamada, linux-kselftest The only-root-readable /sys/module/$module/sections/$section files did not truncate their output to the available buffer size. While most paths into the kernfs read handlers end up using PAGE_SIZE buffers, it's possible to get there through other paths (e.g. splice, sendfile). Actually limit the output to the "count" passed into the read function, and report it back correctly. *sigh* Reported-by: kernel test robot <lkp@intel.com> Link: https://lore.kernel.org/lkml/20200805002015.GE23458@shao2-debian Fixes: ed66f991bb19 ("module: Refactor section attr into bin attribute") Cc: stable@vger.kernel.org Cc: Jessica Yu <jeyu@kernel.org> Signed-off-by: Kees Cook <keescook@chromium.org> --- kernel/module.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index aa183c9ac0a2..08c46084d8cc 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1520,18 +1520,34 @@ struct module_sect_attrs { struct module_sect_attr attrs[]; }; +#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4)) static ssize_t module_sect_read(struct file *file, struct kobject *kobj, struct bin_attribute *battr, char *buf, loff_t pos, size_t count) { struct module_sect_attr *sattr = container_of(battr, struct module_sect_attr, battr); + char bounce[MODULE_SECT_READ_SIZE + 1]; + size_t wrote; if (pos != 0) return -EINVAL; - return sprintf(buf, "0x%px\n", - kallsyms_show_value(file->f_cred) ? (void *)sattr->address : NULL); + /* + * Since we're a binary read handler, we must account for the + * trailing NUL byte that sprintf will write: if "buf" is + * too small to hold the NUL, or the NUL is exactly the last + * byte, the read will look like it got truncated by one byte. + * Since there is no way to ask sprintf nicely to not write + * the NUL, we have to use a bounce buffer. + */ + wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n", + kallsyms_show_value(file->f_cred) + ? (void *)sattr->address : NULL); + count = min(count, wrote); + memcpy(buf, bounce, count); + + return count; } static void free_sect_attrs(struct module_sect_attrs *sect_attrs) @@ -1580,7 +1596,7 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info) goto out; sect_attrs->nsections++; sattr->battr.read = module_sect_read; - sattr->battr.size = 3 /* "0x", "\n" */ + (BITS_PER_LONG / 4); + sattr->battr.size = MODULE_SECT_READ_SIZE; sattr->battr.attr.mode = 0400; *(gattr++) = &(sattr++)->battr; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] module: Correctly truncate sysfs sections output 2020-08-07 6:35 ` [PATCH 1/2] " Kees Cook @ 2020-08-07 6:47 ` Greg Kroah-Hartman 2020-08-07 13:18 ` Jessica Yu 1 sibling, 0 replies; 5+ messages in thread From: Greg Kroah-Hartman @ 2020-08-07 6:47 UTC (permalink / raw) To: Kees Cook Cc: linux-kernel, kernel test robot, stable, Jessica Yu, Shuah Khan, Masahiro Yamada, linux-kselftest On Thu, Aug 06, 2020 at 11:35:38PM -0700, Kees Cook wrote: > The only-root-readable /sys/module/$module/sections/$section files > did not truncate their output to the available buffer size. While most > paths into the kernfs read handlers end up using PAGE_SIZE buffers, > it's possible to get there through other paths (e.g. splice, sendfile). > Actually limit the output to the "count" passed into the read function, > and report it back correctly. *sigh* Ugh, never thought about that... Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] module: Correctly truncate sysfs sections output 2020-08-07 6:35 ` [PATCH 1/2] " Kees Cook 2020-08-07 6:47 ` Greg Kroah-Hartman @ 2020-08-07 13:18 ` Jessica Yu 1 sibling, 0 replies; 5+ messages in thread From: Jessica Yu @ 2020-08-07 13:18 UTC (permalink / raw) To: Kees Cook Cc: linux-kernel, kernel test robot, stable, Shuah Khan, Greg Kroah-Hartman, Masahiro Yamada, linux-kselftest +++ Kees Cook [06/08/20 23:35 -0700]: >The only-root-readable /sys/module/$module/sections/$section files >did not truncate their output to the available buffer size. While most >paths into the kernfs read handlers end up using PAGE_SIZE buffers, >it's possible to get there through other paths (e.g. splice, sendfile). >Actually limit the output to the "count" passed into the read function, >and report it back correctly. *sigh* > >Reported-by: kernel test robot <lkp@intel.com> >Link: https://lore.kernel.org/lkml/20200805002015.GE23458@shao2-debian >Fixes: ed66f991bb19 ("module: Refactor section attr into bin attribute") >Cc: stable@vger.kernel.org >Cc: Jessica Yu <jeyu@kernel.org> >Signed-off-by: Kees Cook <keescook@chromium.org> Oof, thanks for fixing this! Acked-by: Jessica Yu <jeyu@kernel.org> >--- > kernel/module.c | 22 +++++++++++++++++++--- > 1 file changed, 19 insertions(+), 3 deletions(-) > >diff --git a/kernel/module.c b/kernel/module.c >index aa183c9ac0a2..08c46084d8cc 100644 >--- a/kernel/module.c >+++ b/kernel/module.c >@@ -1520,18 +1520,34 @@ struct module_sect_attrs { > struct module_sect_attr attrs[]; > }; > >+#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4)) > static ssize_t module_sect_read(struct file *file, struct kobject *kobj, > struct bin_attribute *battr, > char *buf, loff_t pos, size_t count) > { > struct module_sect_attr *sattr = > container_of(battr, struct module_sect_attr, battr); >+ char bounce[MODULE_SECT_READ_SIZE + 1]; >+ size_t wrote; > > if (pos != 0) > return -EINVAL; > >- return sprintf(buf, "0x%px\n", >- kallsyms_show_value(file->f_cred) ? (void *)sattr->address : NULL); >+ /* >+ * Since we're a binary read handler, we must account for the >+ * trailing NUL byte that sprintf will write: if "buf" is >+ * too small to hold the NUL, or the NUL is exactly the last >+ * byte, the read will look like it got truncated by one byte. >+ * Since there is no way to ask sprintf nicely to not write >+ * the NUL, we have to use a bounce buffer. >+ */ >+ wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n", >+ kallsyms_show_value(file->f_cred) >+ ? (void *)sattr->address : NULL); >+ count = min(count, wrote); >+ memcpy(buf, bounce, count); >+ >+ return count; > } > > static void free_sect_attrs(struct module_sect_attrs *sect_attrs) >@@ -1580,7 +1596,7 @@ static void add_sect_attrs(struct module *mod, const struct load_info *info) > goto out; > sect_attrs->nsections++; > sattr->battr.read = module_sect_read; >- sattr->battr.size = 3 /* "0x", "\n" */ + (BITS_PER_LONG / 4); >+ sattr->battr.size = MODULE_SECT_READ_SIZE; > sattr->battr.attr.mode = 0400; > *(gattr++) = &(sattr++)->battr; > } >-- >2.25.1 > ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] selftests: splice: Check behavior of full and short splices 2020-08-07 6:35 [PATCH 0/2] module: Correctly truncate sysfs sections output Kees Cook 2020-08-07 6:35 ` [PATCH 1/2] " Kees Cook @ 2020-08-07 6:35 ` Kees Cook 1 sibling, 0 replies; 5+ messages in thread From: Kees Cook @ 2020-08-07 6:35 UTC (permalink / raw) To: linux-kernel Cc: Kees Cook, Shuah Khan, Jessica Yu, Greg Kroah-Hartman, Masahiro Yamada, linux-kselftest 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> --- tools/testing/selftests/splice/.gitignore | 1 + tools/testing/selftests/splice/Makefile | 4 +- tools/testing/selftests/splice/config | 1 + tools/testing/selftests/splice/settings | 1 + .../selftests/splice/short_splice_read.sh | 56 ++++++++++++++++++ tools/testing/selftests/splice/splice_read.c | 57 +++++++++++++++++++ 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/splice/config create mode 100644 tools/testing/selftests/splice/settings create mode 100755 tools/testing/selftests/splice/short_splice_read.sh create mode 100644 tools/testing/selftests/splice/splice_read.c diff --git a/tools/testing/selftests/splice/.gitignore b/tools/testing/selftests/splice/.gitignore index d5a2da428752..be8266f5d04c 100644 --- a/tools/testing/selftests/splice/.gitignore +++ b/tools/testing/selftests/splice/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only default_file_splice_read +splice_read diff --git a/tools/testing/selftests/splice/Makefile b/tools/testing/selftests/splice/Makefile index e519b159b60d..541cd826d5a5 100644 --- a/tools/testing/selftests/splice/Makefile +++ b/tools/testing/selftests/splice/Makefile @@ -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 diff --git a/tools/testing/selftests/splice/config b/tools/testing/selftests/splice/config new file mode 100644 index 000000000000..058c928368b8 --- /dev/null +++ b/tools/testing/selftests/splice/config @@ -0,0 +1 @@ +CONFIG_TEST_LKM=m diff --git a/tools/testing/selftests/splice/settings b/tools/testing/selftests/splice/settings new file mode 100644 index 000000000000..89cedfc0d12b --- /dev/null +++ b/tools/testing/selftests/splice/settings @@ -0,0 +1 @@ +timeout=5 diff --git a/tools/testing/selftests/splice/short_splice_read.sh b/tools/testing/selftests/splice/short_splice_read.sh new file mode 100755 index 000000000000..7810d3589d9a --- /dev/null +++ b/tools/testing/selftests/splice/short_splice_read.sh @@ -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 diff --git a/tools/testing/selftests/splice/splice_read.c b/tools/testing/selftests/splice/splice_read.c new file mode 100644 index 000000000000..46dae6a25cfb --- /dev/null +++ b/tools/testing/selftests/splice/splice_read.c @@ -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; +} -- 2.25.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-08-07 13:18 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-08-07 6:35 [PATCH 0/2] module: Correctly truncate sysfs sections output Kees Cook 2020-08-07 6:35 ` [PATCH 1/2] " Kees Cook 2020-08-07 6:47 ` Greg Kroah-Hartman 2020-08-07 13:18 ` Jessica Yu 2020-08-07 6:35 ` [PATCH 2/2] selftests: splice: Check behavior of full and short splices Kees Cook
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.