lkml.org 
[lkml]   [2020]   [Aug]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 087/204] module: Correctly truncate sysfs sections output
    Date
    From: Kees Cook <keescook@chromium.org>

    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: 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
    Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Acked-by: Jessica Yu <jeyu@kernel.org>
    Signed-off-by: Kees Cook <keescook@chromium.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/module.c | 22 +++++++++++++++++++---
    1 file changed, 19 insertions(+), 3 deletions(-)

    --- a/kernel/module.c
    +++ b/kernel/module.c
    @@ -1517,18 +1517,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)
    @@ -1577,7 +1593,7 @@ static void add_sect_attrs(struct module
    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;
    }

    \
     
     \ /
      Last update: 2020-08-20 15:07    [W:8.875 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site