The patch titled Subject: c/r: prctl: add PR_SET_MM codes to set up mm_struct entries has been added to the -mm tree. Its filename is c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** See http://userweb.kernel.org/~akpm/stuff/added-to-mm.txt to find out what to do about this The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/ ------------------------------------------------------ From: Cyrill Gorcunov <gorcunov@xxxxxxxxxx> Subject: c/r: prctl: add PR_SET_MM codes to set up mm_struct entries When we restore a task we need to set up text, data and data heap sizes from userspace to the values a task had at checkpoint time. This patch adds auxilary prctl codes for that. While most of them have a statistical nature (their values are involved into calculation of /proc/<pid>/statm output) the start_brk and brk values are used to compute an allowed size of program data segment expansion. Which means an arbitrary changes of this values might be dangerous operation. So to restrict access the following requirements applied to prctl calls: - The process has to have CAP_SYS_ADMIN capability granted. - For all opcodes except start_brk/brk members an appropriate VMA area must exist and should fit certain VMA flags, such as: - code segment must be executable but not writable; - data segment must not be executable. start_brk/brk values must not intersect with data segment and must not exceed RLIMIT_DATA resource limit. Still the main guard is CAP_SYS_ADMIN capability check. Note the kernel should be compiled with CONFIG_CHECKPOINT_RESTORE support otherwise these prctl calls will return -EINVAL. Signed-off-by: Cyrill Gorcunov <gorcunov@xxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Reviewed-by: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Tejun Heo <tj@xxxxxxxxxx> Cc: Andrew Vagin <avagin@xxxxxxxxxx> Cc: Serge Hallyn <serge.hallyn@xxxxxxxxxxxxx> Cc: Pavel Emelyanov <xemul@xxxxxxxxxxxxx> Cc: Vasiliy Kulikov <segoon@xxxxxxxxxxxx> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@xxxxxxxxxxxxxx> Cc: Michael Kerrisk <mtk.manpages@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/prctl.h | 12 ++++ kernel/sys.c | 120 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff -puN include/linux/prctl.h~c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries include/linux/prctl.h --- a/include/linux/prctl.h~c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries +++ a/include/linux/prctl.h @@ -102,4 +102,16 @@ #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 + #endif /* _LINUX_PRCTL_H */ diff -puN kernel/sys.c~c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries kernel/sys.c --- a/kernel/sys.c~c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries +++ a/kernel/sys.c @@ -1692,6 +1692,123 @@ SYSCALL_DEFINE1(umask, int, mask) return mask; } +#ifdef CONFIG_CHECKPOINT_RESTORE +static int prctl_set_mm(int opt, unsigned long addr, + unsigned long arg4, unsigned long arg5) +{ + unsigned long rlim = rlimit(RLIMIT_DATA); + unsigned long vm_req_flags; + unsigned long vm_bad_flags; + struct vm_area_struct *vma; + int error = 0; + + if (arg4 | arg5) + return -EINVAL; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (addr >= TASK_SIZE) + return -EINVAL; + + down_read(¤t->mm->mmap_sem); + vma = find_vma(current->mm, addr); + + if (opt != PR_SET_MM_START_BRK && opt != PR_SET_MM_BRK) { + /* It must be existing VMA */ + if (!vma || vma->vm_start > addr) + goto out; + } + + error = -EINVAL; + switch (opt) { + case PR_SET_MM_START_CODE: + case PR_SET_MM_END_CODE: + vm_req_flags = VM_READ | VM_EXEC; + vm_bad_flags = VM_WRITE | VM_MAYSHARE; + + if ((vma->vm_flags & vm_req_flags) != vm_req_flags || + (vma->vm_flags & vm_bad_flags)) + goto out; + + if (opt == PR_SET_MM_START_CODE) + current->mm->start_code = addr; + else + current->mm->end_code = addr; + break; + + case PR_SET_MM_START_DATA: + case PR_SET_MM_END_DATA: + vm_req_flags = VM_READ | VM_WRITE; + vm_bad_flags = VM_EXEC | VM_MAYSHARE; + + if ((vma->vm_flags & vm_req_flags) != vm_req_flags || + (vma->vm_flags & vm_bad_flags)) + goto out; + + if (opt == PR_SET_MM_START_DATA) + current->mm->start_data = addr; + else + current->mm->end_data = addr; + break; + + case PR_SET_MM_START_STACK: + +#ifdef CONFIG_STACK_GROWSUP + vm_req_flags = VM_READ | VM_WRITE | VM_GROWSUP; +#else + vm_req_flags = VM_READ | VM_WRITE | VM_GROWSDOWN; +#endif + if ((vma->vm_flags & vm_req_flags) != vm_req_flags) + goto out; + + current->mm->start_stack = addr; + break; + + case PR_SET_MM_START_BRK: + if (addr <= current->mm->end_data) + goto out; + + if (rlim < RLIM_INFINITY && + (current->mm->brk - addr) + + (current->mm->end_data - current->mm->start_data) > rlim) + goto out; + + current->mm->start_brk = addr; + break; + + case PR_SET_MM_BRK: + if (addr <= current->mm->end_data) + goto out; + + if (rlim < RLIM_INFINITY && + (addr - current->mm->start_brk) + + (current->mm->end_data - current->mm->start_data) > rlim) + goto out; + + current->mm->brk = addr; + break; + + default: + error = -EINVAL; + goto out; + } + + error = 0; + +out: + up_read(¤t->mm->mmap_sem); + + return error; +} +#else /* CONFIG_CHECKPOINT_RESTORE */ +static int prctl_set_mm(int opt, unsigned long addr, + unsigned long arg4, unsigned long arg5) +{ + return -EINVAL; +} +#endif + SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) { @@ -1841,6 +1958,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsi else error = PR_MCE_KILL_DEFAULT; break; + case PR_SET_MM: + error = prctl_set_mm(arg2, arg3, arg4, arg5); + break; default: error = -EINVAL; break; _ Subject: Subject: c/r: prctl: add PR_SET_MM codes to set up mm_struct entries Patches currently in -mm which might be from gorcunov@xxxxxxxxxx are linux-next.patch procfs-make-proc_get_link-to-use-dentry-instead-of-inode.patch procfs-introduce-the-proc-pid-map_files-directory.patch procfs-introduce-the-proc-pid-map_files-directory-checkpatch-fixes.patch sysctl-add-the-kernelns_last_pid-control.patch c-r-introduce-checkpoint_restore-symbol.patch c-r-procfs-add-start_data-end_data-start_brk-members-to-proc-pid-stat-v4.patch c-r-procfs-add-start_data-end_data-start_brk-members-to-proc-pid-stat-v4-fix.patch c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries.patch c-r-prctl-add-pr_set_mm-codes-to-set-up-mm_struct-entries-fix.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html