lkml.org 
[lkml]   [2015]   [Apr]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
SubjectRe: Hang on large copy_from_user with PREEMPT_NONE
From
On Tue, Apr 7, 2015 at 10:00 AM, Sasha Levin <sasha.levin@oracle.com> wrote:
>
> It locks up quickly without KASan as well.

I suspect it's some virtualization artifact, where the writes cause
COW faults (or just memory allocations) in the L0 domain.

Whatever. It's probably not worth fighting. Either we just decide that
"copy_from_user()" shouldn't bother to zero huge areas (limit the
zeroing to some arbitrary size), or we just special-case the module
loading.

Something like the attached patch.

Entirely untested, as usual.

Linus
kernel/module.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/kernel/module.c b/kernel/module.c
index 99fdf94efce8..ec53f594e9c9 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2479,6 +2479,23 @@ static int elf_header_check(struct load_info *info)
return 0;
}

+#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
+
+static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned long len)
+{
+ do {
+ unsigned long n = min(len, COPY_CHUNK_SIZE);
+
+ if (copy_from_user(dst, usrc, n) != 0)
+ return -EFAULT;
+ cond_resched();
+ dst += n;
+ usrc += n;
+ len -= n;
+ } while (len);
+ return 0;
+}
+
/* Sets info->hdr and info->len. */
static int copy_module_from_user(const void __user *umod, unsigned long len,
struct load_info *info)
@@ -2498,7 +2515,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
if (!info->hdr)
return -ENOMEM;

- if (copy_from_user(info->hdr, umod, info->len) != 0) {
+ if (copy_chunked_from_user(info->hdr, umod, info->len) != 0) {
vfree(info->hdr);
return -EFAULT;
}
\
 
 \ /
  Last update: 2015-04-07 20:01    [W:0.048 / U:1.608 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site