[Yaffs] [PATCH] vfs: fix proc write for recent kernels

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Martin Kaiser
Date:  
To: yaffs
CC: cdhmanning, Martin Kaiser
Subject: [Yaffs] [PATCH] vfs: fix proc write for recent kernels
From: Martin Kaiser <>

For recent Linux kernels, we receive a user-space pointer in
yaffs_proc_write(). Run copy_from_user() on this pointer before
processing it.

Without this patch, writing to /proc/yaffs causes a page domain fault
since the user-space pointer is used directly.

[root@martin-next ]# echo +all > /proc/yaffs
[ 274.352612] Unhandled fault: page domain fault (0x01b) at 0x01250008
[ 274.359029] pgd = d3bf4000
[ 274.361763] [01250008] *pgd=93bf9831, *pte=8162f14f, *ppte=8162fffe
[ 274.368095] Internal error: : 1b [#1] ARM
[ 274.372129] Modules linked in: yaffs [last unloaded: yaffs]
[ 274.377769] CPU: 0 PID: 162 Comm: echo Not tainted 4.14.0-rc1-next-20170920+ #166

Distinguish between the two cases (old or recent kernel) at the start of
the write function, don't touch the code that processes the actual
input. Remove const qualifiers if necessary.

Signed-off-by: Martin Kaiser <>
---
yaffs_vfs_multi.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c
index acb0c4a..0ec1234 100644
--- a/yaffs_vfs_multi.c
+++ b/yaffs_vfs_multi.c
@@ -3415,7 +3415,7 @@ static struct {
};

 #define MAX_MASK_NAME_LENGTH 40
-static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
+static int yaffs_proc_write_trace_options(struct file *file, char *buf,
                       unsigned long count)
 {
     unsigned rg = 0, mask_bitfield;
@@ -3516,7 +3516,7 @@ static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
  * .cobjn,chunkn print nand chunk id for objn:chunkn
  */


-static int yaffs_proc_debug_write(struct file *file, const char *buf,
+static int yaffs_proc_debug_write(struct file *file, char *buf,
                       unsigned long count)
 {


@@ -3596,14 +3596,23 @@ static int yaffs_proc_debug_write(struct file *file, const char *buf,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
 static int yaffs_proc_write(struct file *file, const char *buf,
                 unsigned long count, void *ppos)
+{
+    char *_buf = (char *)buf;
+    unsigned long _buf_len = count;
 #else
 static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
                 size_t count, loff_t *ppos)
-#endif
 {
-    if (buf[0] == '.')
-        return yaffs_proc_debug_write(file, buf, count);
-    return yaffs_proc_write_trace_options(file, buf, count);
+    char _buf[512];
+    unsigned long _buf_len = min(count, sizeof(_buf));
+
+    if (copy_from_user(_buf, buf, _buf_len))
+        return -EFAULT;
+#endif
+
+    if (_buf[0] == '.')
+        return yaffs_proc_debug_write(file, _buf, _buf_len);
+    return yaffs_proc_write_trace_options(file, _buf, _buf_len);
 }


/* Stuff to handle installation of file systems */
--
2.1.4