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