proc_read_simdisk() looks at dev->filename without holding dev->lock. A
write to the same file detaches the disk and frees the name under the
lock, so a concurrent reader can copy out freed memory. Copy the name
with the lock held.

Fixes: b6c7e873daf7 ("xtensa: ISS: add host file-based simulated disk")
Cc: [email protected]
Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 arch/xtensa/platforms/iss/simdisk.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/arch/xtensa/platforms/iss/simdisk.c 
b/arch/xtensa/platforms/iss/simdisk.c
index a2ddb49c269d..7b115e023de9 100644
--- a/arch/xtensa/platforms/iss/simdisk.c
+++ b/arch/xtensa/platforms/iss/simdisk.c
@@ -238,22 +238,21 @@ static ssize_t proc_read_simdisk(struct file *file, char 
__user *buf,
                        size_t size, loff_t *ppos)
 {
        struct simdisk *dev = pde_data(file_inode(file));
-       const char *s = dev->filename;
-       if (s) {
-               ssize_t len = strlen(s);
-               char *temp = kmalloc(len + 2, GFP_KERNEL);
+       ssize_t len;
+       char *temp;
 
-               if (!temp)
-                       return -ENOMEM;
+       /* a write sets at most a page, see proc_write_simdisk() */
+       temp = kmalloc(PAGE_SIZE + 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);
+       spin_lock(&dev->lock);
+       len = scnprintf(temp, PAGE_SIZE + 2, "%s\n", dev->filename ?: "");
+       spin_unlock(&dev->lock);
 
-               kfree(temp);
-               return len;
-       }
-       return simple_read_from_buffer(buf, size, ppos, "\n", 1);
+       len = simple_read_from_buffer(buf, size, ppos, temp, len);
+       kfree(temp);
+       return len;
 }
 
 static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,

-- 
2.53.0


Reply via email to