prctl: Add PR_ codes to restore vDSO and tune up mm_struct entires
RFC 1/1 prctl: Add PR_ codes to restore vDSO and tune up mm_struct entires
While doing restore of a task we need to setup vDSO at predefined address unmapping current one and tune up mm_struct members which are set at Elf loading stage.
So I would like to know what people think about the patch below? Maybe I miss something and we already have some convenient way to deal with it?
Complains are highly appreciated!
---
From: Cyrill Gorcunov <[email protected]>
Date: Tue, 22 Nov 2011 21:08:43 +0400
Subject: [PATCH] prctl: Add PR_ codes to restore vDSO and tune up mm_struct entires
To be able to use vDSO facility at process restore time we need it being mapped at predefined address (at the address it had at checkpoint time). For this sake PR_SETUP_VDSO_AT is introduced.
Same time a few members in mm_struct are set up by a binfmt handler code, such as mm_struct -> start_code, end_code, start_data, end_data, start_stack, start_brk, brk. So at restore time we need them to have exactly the same values as they had at checkpoint time. This is handled by PR_SET_MM prctl opcode.
--- arch/x86/vdso/vma.c | 39 +++++++++++++++++++++++++++ include/linux/prctl.h | 18 ++++++++++++ kernel/sys.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 0 deletions(-)
arch/x86/vdso/vma.c +39 -0
@@ -137,6 +137,45 @@ up_fail:return ret; } +int arch_setup_additional_pages_at (void *addr) +{ +struct mm_struct *mm = current->mm; +int ret; + +if (!vdso_enabled) +return 0 ; + +if ((unsigned long )addr >TASK_SIZE - vdso_size) +return -ENOMEM ; + +if ((unsigned long )addr & ~PAGE_MASK ) +return -EINVAL ; + +down_write (&mm->mmap_sem); + +/* +* Unmap previous entry. +*/ +if (mm->context.vdso) { + ret =do_munmap (mm, (unsigned long )mm->context.vdso, vdso_size); +if (ret) + goto err; + } + + mm->context.vdso = addr; + ret =install_special_mapping (mm, (unsigned long )addr, vdso_size, +VM_READ |VM_EXEC | +VM_MAYREAD |VM_MAYWRITE |VM_MAYEXEC | +VM_ALWAYSDUMP , + vdso_pages); +if (ret) + mm->context.vdso =NULL ; + +err: +up_write (&mm->mmap_sem); +return ret; +} +static __init int vdso_setup (char *s) { vdso_enabled =simple_strtoul (s,NULL ,0 );
include/linux/prctl.h +18 -0
@@ -102,4 +102,22 @@#define PR_MCE_KILL_GET 34 +/* +* Tune up process memory map specifics. +*/ +#define PR_SET_MM 35 +# define PR_SET_MM_START_CODE 1 +# define PR_SET_MM_END_CODE 2 +# define PR_SET_MM_START_DATA 3 +# define PR_SET_MM_END_DATA 4 +# define PR_SET_MM_START_STACK 5 +# define PR_SET_MM_START_BRK 6 +# define PR_SET_MM_BRK 7 + +/* +* Unmap current vDSO and setup new one +* at predefined address. +*/ +#define PR_SETUP_VDSO_AT 36 +#endif /* _LINUX_PRCTL_H */
kernel/sys.c +71 -0
83 lines not on this page · raw message
Signature · 1 line
1.7.7.3
Hello, Cyrill.
kernel/sys.c SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, · line 1862
Quoted 13 lines · Cyrill Gorcunov
kernel/sys.c +13
-0+case PR_SETUP_VDSO_AT : +if (arg3 | arg4 | arg5) +return -EINVAL ; + +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ; + +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES + error =arch_setup_additional_pages_at ((void *)arg2); +#else + error = -ENOSYS ; +#endif +break ;
Hmmm... I'm not sure this is the best approach. vdso is supposed to be able to be dependent on binprm too, so the proposed solution could work but I'm not sure whether it's a good one. For now, can't we just copy the vdso and unmap it at the orignal address?
Thanks.
Signature · 1 line
tejun
Quoted 11 lines · Tejun Heo
Quoted 10 lines · Cyrill Gorcunov
kernel/sys.c +10
-0+case PR_SETUP_VDSO_AT : +if (arg3 | arg4 | arg5) +return -EINVAL ; + +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ; + +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES + error =arch_setup_additional_pages_at ((void *)arg2); +#else
Quoted 9 lines
kernel/sys.c SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, · line 1862
Quoted 3 lines
kernel/sys.c +3
-0+ error = -ENOSYS ; +#endif +break ;Hmmm... I'm not sure this is the best approach. vdso is supposed to be able to be dependent on binprm too, so the proposed solution could work but I'm not sure whether it's a good one. For now, can't we just copy the vdso and unmap it at the orignal address?
Hi Tejun,
yeah, it might be not that good solution (RFC it was(c) ;) but I actually failed to find some more elegant way of handling it. So you propose to handle all the things directly in userspatce, ie unmap current, map previous vdso)? (I fear mapping vsyscall is not allowed from userspace but I'll check)