Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cec9fbfe authored by Kees Cook's avatar Kees Cook Committed by Greg Kroah-Hartman
Browse files

module: Correctly truncate sysfs sections output



commit 11990a5bd7e558e9203c1070fc52fb6f0488e75b upstream.

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: default avatarkernel 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
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: default avatarJessica Yu <jeyu@kernel.org>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 73f74fc3
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -1461,18 +1461,34 @@ struct module_sect_attrs {
	struct module_sect_attr attrs[0];
};

#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)
@@ -1521,7 +1537,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;
	}