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.

$ 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);
}


Reply via email to