Messages in this thread Patch in this message | | | Date | Tue, 7 Apr 2015 10:33:49 -0700 | Subject | Re: Hang on large copy_from_user with PREEMPT_NONE | From | Linus Torvalds <> |
| |
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; } | |