diff options
| author | Konstantin Khlebnikov <khlebnikov@openvz.org> | 2012-06-07 14:21:11 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-07 14:43:55 -0700 | 
| commit | bafb282df29c1524b1617019adebd6d0c3eb7a47 (patch) | |
| tree | f0b9efa850b4b298ce484eead5c8d9de87dde3e9 /kernel/sys.c | |
| parent | 6305902c2f871fd6db60af367bd7120fa977fa74 (diff) | |
| download | olio-linux-3.10-bafb282df29c1524b1617019adebd6d0c3eb7a47.tar.xz olio-linux-3.10-bafb282df29c1524b1617019adebd6d0c3eb7a47.zip  | |
c/r: prctl: update prctl_set_mm_exe_file() after mm->num_exe_file_vmas removal
A fix for commit b32dfe377102 ("c/r: prctl: add ability to set new
mm_struct::exe_file").
After removing mm->num_exe_file_vmas kernel keeps mm->exe_file until
final mmput(), it never becomes NULL while task is alive.
We can check for other mapped files in mm instead of checking
mm->num_exe_file_vmas, and mark mm with flag MMF_EXE_FILE_CHANGED in
order to forbid second changing of mm->exe_file.
Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Matt Helsley <matthltc@us.ibm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 31 | 
1 files changed, 19 insertions, 12 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 9ff89cb9657..54f20fdee93 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1796,17 +1796,11 @@ static bool vma_flags_mismatch(struct vm_area_struct *vma,  static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)  { +	struct vm_area_struct *vma;  	struct file *exe_file;  	struct dentry *dentry;  	int err; -	/* -	 * Setting new mm::exe_file is only allowed when no VM_EXECUTABLE vma's -	 * remain. So perform a quick test first. -	 */ -	if (mm->num_exe_file_vmas) -		return -EBUSY; -  	exe_file = fget(fd);  	if (!exe_file)  		return -EBADF; @@ -1827,17 +1821,30 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)  	if (err)  		goto exit; +	down_write(&mm->mmap_sem); + +	/* +	 * Forbid mm->exe_file change if there are mapped other files. +	 */ +	err = -EBUSY; +	for (vma = mm->mmap; vma; vma = vma->vm_next) { +		if (vma->vm_file && !path_equal(&vma->vm_file->f_path, +						&exe_file->f_path)) +			goto exit_unlock; +	} +  	/*  	 * The symlink can be changed only once, just to disallow arbitrary  	 * transitions malicious software might bring in. This means one  	 * could make a snapshot over all processes running and monitor  	 * /proc/pid/exe changes to notice unusual activity if needed.  	 */ -	down_write(&mm->mmap_sem); -	if (likely(!mm->exe_file)) -		set_mm_exe_file(mm, exe_file); -	else -		err = -EBUSY; +	err = -EPERM; +	if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) +		goto exit_unlock; + +	set_mm_exe_file(mm, exe_file); +exit_unlock:  	up_write(&mm->mmap_sem);  exit:  |