Commit 1a2ed27b authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

prctl: restore -- Use new PR_SET_MM_MAP if kernel supports

This would allow to restore parameters with user namespaces
enabled.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 8c40f430
...@@ -754,6 +754,7 @@ long __export_restore_task(struct task_restore_args *args) ...@@ -754,6 +754,7 @@ long __export_restore_task(struct task_restore_args *args)
unsigned long va; unsigned long va;
struct rt_sigframe *rt_sigframe; struct rt_sigframe *rt_sigframe;
struct prctl_mm_map prctl_map;
unsigned long new_sp; unsigned long new_sp;
k_rtsigset_t to_block; k_rtsigset_t to_block;
pid_t my_pid = sys_getpid(); pid_t my_pid = sys_getpid();
...@@ -921,30 +922,56 @@ long __export_restore_task(struct task_restore_args *args) ...@@ -921,30 +922,56 @@ long __export_restore_task(struct task_restore_args *args)
/* /*
* Tune up the task fields. * Tune up the task fields.
*/ */
ret |= sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0); ret = sys_prctl_safe(PR_SET_NAME, (long)args->comm, 0, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm_saved_auxv, args->mm_saved_auxv_size);
if (ret) if (ret)
goto core_restore_end; goto core_restore_end;
/* /*
* Because of requirements applied from kernel side * New kernel interface with @PR_SET_MM_MAP will become
* we need to restore /proc/pid/exe symlink late, * more widespread once kernel get deployed over the world.
* after old existing VMAs are superseded with * Thus lets be opportunistic and use new inteface as a try.
* new ones from image file.
*/ */
ret = restore_self_exe_late(args); prctl_map = (struct prctl_mm_map) {
.start_code = args->mm.mm_start_code,
.end_code = args->mm.mm_end_code,
.start_data = args->mm.mm_start_data,
.end_data = args->mm.mm_end_data,
.start_stack = args->mm.mm_start_stack,
.start_brk = args->mm.mm_start_brk,
.brk = args->mm.mm_brk,
.arg_start = args->mm.mm_arg_start,
.arg_end = args->mm.mm_arg_end,
.env_start = args->mm.mm_env_start,
.env_end = args->mm.mm_env_end,
.auxv = (void *)args->mm_saved_auxv,
.auxv_size = args->mm_saved_auxv_size,
.exe_fd = args->fd_exe_link,
};
ret = sys_prctl(PR_SET_MM, PR_SET_MM_MAP, (long)&prctl_map, sizeof(prctl_map), 0);
if (ret == -EINVAL) {
ret = sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm_saved_auxv, args->mm_saved_auxv_size);
/*
* Because of requirements applied from kernel side
* we need to restore /proc/pid/exe symlink late,
* after old existing VMAs are superseded with
* new ones from image file.
*/
ret |= restore_self_exe_late(args);
} else
sys_close(args->fd_exe_link);
if (ret) if (ret)
goto core_restore_end; goto core_restore_end;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment