* [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
* [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
* 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
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).