diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 22 | 
1 files changed, 19 insertions, 3 deletions
diff --git a/kernel/module.c b/kernel/module.c index e7b4ff7e4fd0..8fa2600bde6a 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;  	}  | 
