xtensa/simdisk: fix proc_read_simdisk()
authorYi Yang <yiyang13@huawei.com>
Tue, 10 May 2022 08:05:33 +0000 (16:05 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:23:28 +0000 (10:23 +0200)
commit b011946d039d66bbc7102137e98cc67e1356aa87 upstream.

The commit a69755b18774 ("xtensa simdisk: switch to proc_create_data()")
split read operation into two parts, first retrieving the path when it's
non-null and second retrieving the trailing '\n'. However when the path
is non-null the first simple_read_from_buffer updates ppos, and the
second simple_read_from_buffer returns 0 if ppos is greater than 1 (i.e.
almost always). As a result reading from that proc file is almost always
empty.

Fix it by making a temporary copy of the path with the trailing '\n' and
using simple_read_from_buffer on that copy.

Cc: stable@vger.kernel.org
Fixes: a69755b18774 ("xtensa simdisk: switch to proc_create_data()")
Signed-off-by: Yi Yang <yiyang13@huawei.com>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/xtensa/platforms/iss/simdisk.c

index 3cdfa00..edb2764 100644 (file)
@@ -212,12 +212,18 @@ static ssize_t proc_read_simdisk(struct file *file, char __user *buf,
        struct simdisk *dev = PDE_DATA(file_inode(file));
        const char *s = dev->filename;
        if (s) {
-               ssize_t n = simple_read_from_buffer(buf, size, ppos,
-                                                       s, strlen(s));
-               if (n < 0)
-                       return n;
-               buf += n;
-               size -= n;
+               ssize_t len = strlen(s);
+               char *temp = kmalloc(len + 2, GFP_KERNEL);
+
+               if (!temp)
+                       return -ENOMEM;
+
+               len = scnprintf(temp, len + 2, "%s\n", s);
+               len = simple_read_from_buffer(buf, size, ppos,
+                                             temp, len);
+
+               kfree(temp);
+               return len;
        }
        return simple_read_from_buffer(buf, size, ppos, "\n", 1);
 }