On Sat, 29 Aug 2020, Joe Perches wrote: > On Sat, 2020-08-29 at 16:48 -0700, Joe Perches wrote: > > Output defects can exist in sysfs content using sprintf and snprintf. > > > > sprintf does not know the PAGE_SIZE maximum of the temporary buffer > > used for outputting sysfs content and it's possible to overrun the > > PAGE_SIZE buffer length. > > > > Add a generic sysfs_emit function that knows that the size of the > > temporary buffer and ensures that no overrun is done. > > > > Add a generic sysfs_emit_at function that can be used in multiple > > call situations that also ensures that no overrun is done. > > This preliminary coccinelle script converts ~5000 instances treewide. > There are still many remaining instances that could be converted. Except for the issue with the ...s that has been discussed, this looks basically reasonable to me. julia > > $ git grep -w sysfs_emit -- '*.[ch]'|wc -l > 4702 > $ git grep -w sysfs_emit_at -- '*.[ch]'|wc -l > 229 > > $ cat sysfs_emit.cocci > @@ > identifier d_show =~ "^.*show.*$"; > identifier arg1, arg2, arg3; > @@ > ssize_t d_show(struct device * > - arg1 > + dev > , struct device_attribute * > - arg2 > + attr > , char * > - arg3 > + buf > ) > { > ... > ( > - arg1 > + dev > | > - arg2 > + attr > | > - arg3 > + buf > ) > ... > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > return > - sprintf(buf, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > return > - snprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > return > - scnprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > expression chr; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > return > - strcpy(buf, chr); > + sysfs_emit(buf, chr); > ...> > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > identifier len; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > len = > - sprintf(buf, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > identifier len; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > len = > - snprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > identifier len; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > len = > - scnprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > identifier len; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > <... > - len += scnprintf(buf + len, PAGE_SIZE - len, > + len += sysfs_emit_at(buf, len, > ...); > ...> > return len; > } > > @@ > identifier d_show =~ "^.*show.*$"; > identifier dev, attr, buf; > expression chr; > @@ > > ssize_t d_show(struct device *dev, struct device_attribute *attr, char *buf) > { > - strcpy(buf, chr); > - return strlen(buf); > + return sysfs_emit(buf, chr); > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier arg1, arg2, arg3; > @@ > ssize_t k_show(struct kobject * > - arg1 > + kobj > , struct kobj_attribute * > - arg2 > + attr > , char * > - arg3 > + buf > ) > { > ... > ( > - arg1 > + kobj > | > - arg2 > + attr > | > - arg3 > + buf > ) > ... > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > return > - sprintf(buf, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > return > - snprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > return > - scnprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > expression chr; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > return > - strcpy(buf, chr); > + sysfs_emit(buf, chr); > ...> > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > identifier len; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > len = > - sprintf(buf, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > identifier len; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > len = > - snprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > identifier len; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > len = > - scnprintf(buf, PAGE_SIZE, > + sysfs_emit(buf, > ...); > ...> > return len; > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > identifier len; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > <... > - len += scnprintf(buf + len, PAGE_SIZE - len, > + len += sysfs_emit_at(buf, len, > ...); > ...> > return len; > } > > @@ > identifier k_show =~ "^.*show.*$"; > identifier kobj, attr, buf; > expression chr; > @@ > > ssize_t k_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) > { > - strcpy(buf, chr); > - return strlen(buf); > + return sysfs_emit(buf, chr); > } > > >