Skip to content

Commit 11990a5

Browse files
committed
module: Correctly truncate sysfs sections output
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 <[email protected]> Link: https://lore.kernel.org/lkml/20200805002015.GE23458@shao2-debian Fixes: ed66f99 ("module: Refactor section attr into bin attribute") Cc: [email protected] Reviewed-by: Greg Kroah-Hartman <[email protected]> Acked-by: Jessica Yu <[email protected]> Signed-off-by: Kees Cook <[email protected]>
1 parent bcf8768 commit 11990a5

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

kernel/module.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,18 +1520,34 @@ struct module_sect_attrs {
15201520
struct module_sect_attr attrs[];
15211521
};
15221522

1523+
#define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
15231524
static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
15241525
struct bin_attribute *battr,
15251526
char *buf, loff_t pos, size_t count)
15261527
{
15271528
struct module_sect_attr *sattr =
15281529
container_of(battr, struct module_sect_attr, battr);
1530+
char bounce[MODULE_SECT_READ_SIZE + 1];
1531+
size_t wrote;
15291532

15301533
if (pos != 0)
15311534
return -EINVAL;
15321535

1533-
return sprintf(buf, "0x%px\n",
1534-
kallsyms_show_value(file->f_cred) ? (void *)sattr->address : NULL);
1536+
/*
1537+
* Since we're a binary read handler, we must account for the
1538+
* trailing NUL byte that sprintf will write: if "buf" is
1539+
* too small to hold the NUL, or the NUL is exactly the last
1540+
* byte, the read will look like it got truncated by one byte.
1541+
* Since there is no way to ask sprintf nicely to not write
1542+
* the NUL, we have to use a bounce buffer.
1543+
*/
1544+
wrote = scnprintf(bounce, sizeof(bounce), "0x%px\n",
1545+
kallsyms_show_value(file->f_cred)
1546+
? (void *)sattr->address : NULL);
1547+
count = min(count, wrote);
1548+
memcpy(buf, bounce, count);
1549+
1550+
return count;
15351551
}
15361552

15371553
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)
15801596
goto out;
15811597
sect_attrs->nsections++;
15821598
sattr->battr.read = module_sect_read;
1583-
sattr->battr.size = 3 /* "0x", "\n" */ + (BITS_PER_LONG / 4);
1599+
sattr->battr.size = MODULE_SECT_READ_SIZE;
15841600
sattr->battr.attr.mode = 0400;
15851601
*(gattr++) = &(sattr++)->battr;
15861602
}

0 commit comments

Comments
 (0)