mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-28 12:57:57 +00:00
sys_mmap: fixed the error detection logic.
The current sys_mmap error analysis code doesn't work on 32-bit architectures with 3G/1G userspace/kernel virtual address space split since the syscall allocates anonymous memory above the first 2G of the address space --- such an address is a negative integer so it's interpreted as a error code. The problem isn't encountered on x86-64 becauase it doesn't use negative virtual addresses in the userspace. The 3G/1G split is used because memory allocation is currently broken for other values of the split on ARM: the value of TASK_UNMAPPED_BASE (arch/arm/include/asm/memory.h) isn't page-aligned if other split value is used so the value of the field mm_struct::mmap_base is initialized with a page-unaligned value by the function arch_pick_mmap_layout() (arch/arm/mm/mmap.c) in some circumstances that breaks page-alignment checks in the kernel memory management code. This patch modifies sys_mmap return value analysis code replacing tests for negativeness of the signed return value with tests that checks that the return value isn't greater than TASK_SIZE. Signed-off-by: Alexander Kartashov <alekskartashov@parallels.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
b1e8f70b05
commit
3f12d688ae
@ -239,7 +239,7 @@ static void *mmap_seized(struct parasite_ctl *ctl,
|
||||
|
||||
err = syscall_seized(ctl, __NR_mmap, &map,
|
||||
(unsigned long)addr, length, prot, flags, fd, offset);
|
||||
if (err < 0 || (long)map < 0)
|
||||
if (err < 0 || map > TASK_SIZE)
|
||||
map = 0;
|
||||
|
||||
return (void *)map;
|
||||
|
@ -45,7 +45,7 @@ static int brk_init(void)
|
||||
ret = sys_mmap(NULL, MAX_HEAP_SIZE,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (ret < 0)
|
||||
if (ret > TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
brk_start = brk_tail = (void *)ret;
|
||||
@ -427,7 +427,7 @@ static int init(struct parasite_init_args *args)
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1, 0);
|
||||
if ((long)tid_state < 0)
|
||||
if ((unsigned long)tid_state > TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
nr_tid_state = args->nr_threads;
|
||||
|
Loading…
x
Reference in New Issue
Block a user