diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 25 | 
1 files changed, 21 insertions, 4 deletions
diff --git a/fs/exec.c b/fs/exec.c index 4e497b9ee71e..8112eacf10f3 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -209,7 +209,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,  	 * doing the exec and bprm->mm is the new process's mm.  	 */  	ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags, -			&page, NULL); +			&page, NULL, NULL);  	if (ret <= 0)  		return NULL; @@ -1169,8 +1169,10 @@ no_thread_group:  	/* we have changed execution domain */  	tsk->exit_signal = SIGCHLD; +#ifdef CONFIG_POSIX_TIMERS  	exit_itimers(sig);  	flush_itimer_signals(); +#endif  	if (atomic_read(&oldsighand->count) != 1) {  		struct sighand_struct *newsighand; @@ -1275,8 +1277,22 @@ EXPORT_SYMBOL(flush_old_exec);  void would_dump(struct linux_binprm *bprm, struct file *file)  { -	if (inode_permission(file_inode(file), MAY_READ) < 0) +	struct inode *inode = file_inode(file); +	if (inode_permission(inode, MAY_READ) < 0) { +		struct user_namespace *old, *user_ns;  		bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; + +		/* Ensure mm->user_ns contains the executable */ +		user_ns = old = bprm->mm->user_ns; +		while ((user_ns != &init_user_ns) && +		       !privileged_wrt_inode_uidgid(user_ns, inode)) +			user_ns = user_ns->parent; + +		if (old != user_ns) { +			bprm->mm->user_ns = get_user_ns(user_ns); +			put_user_ns(old); +		} +	}  }  EXPORT_SYMBOL(would_dump); @@ -1306,7 +1322,6 @@ void setup_new_exec(struct linux_binprm * bprm)  	    !gid_eq(bprm->cred->gid, current_egid())) {  		current->pdeath_signal = 0;  	} else { -		would_dump(bprm, bprm->file);  		if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)  			set_dumpable(current->mm, suid_dumpable);  	} @@ -1406,7 +1421,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)  	unsigned n_fs;  	if (p->ptrace) { -		if (p->ptrace & PT_PTRACE_CAP) +		if (ptracer_capable(p, current_user_ns()))  			bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;  		else  			bprm->unsafe |= LSM_UNSAFE_PTRACE; @@ -1741,6 +1756,8 @@ static int do_execveat_common(int fd, struct filename *filename,  	if (retval < 0)  		goto out; +	would_dump(bprm, bprm->file); +  	retval = exec_binprm(bprm);  	if (retval < 0)  		goto out;  |