Commit 6ba0d2e4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'kallsyms_show_value-fix-v5.9-rc1' of...

Merge tag 'kallsyms_show_value-fix-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux



Pull sysfs module section fix from Kees Cook:
 "Fix sysfs module section output overflow.

  About a month after my kallsyms_show_value() refactoring landed, 0day
  noticed that there was a path through the kernfs binattr read handlers
  that did not have PAGE_SIZEd buffers, and the module "sections" read
  handler made a bad assumption about this, resulting in it stomping on
  memory when reached through small-sized splice() calls.

  I've added a set of tests to find these kinds of regressions more
  quickly in the future as well"

Sefltests-acked-by: default avatarShuah Khan <skhan@linuxfoundation.org>

* tag 'kallsyms_show_value-fix-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  selftests: splice: Check behavior of full and short splices
  module: Correctly truncate sysfs sections output
parents 1fa2c0a0 9af47666
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -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;
	}
+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
default_file_splice_read
splice_read
+2 −2
Original line number Diff line number Diff line
# 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 −0
Original line number Diff line number Diff line
CONFIG_TEST_LKM=m
+1 −0
Original line number Diff line number Diff line
timeout=5
Loading