diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 32 | 
1 files changed, 21 insertions, 11 deletions
diff --git a/fs/exec.c b/fs/exec.c index 3698252719a3..a91003e28eaa 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -141,12 +141,14 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)  	if (IS_ERR(file))  		goto out; -	error = -EINVAL; -	if (!S_ISREG(file_inode(file)->i_mode)) -		goto exit; - +	/* +	 * may_open() has already checked for this, so it should be +	 * impossible to trip now. But we need to be extra cautious +	 * and check again at the very end too. +	 */  	error = -EACCES; -	if (path_noexec(&file->f_path)) +	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || +			 path_noexec(&file->f_path)))  		goto exit;  	fsnotify_open(file); @@ -215,7 +217,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,  	 * We are doing an exec().  'current' is the process  	 * doing the exec and bprm->mm is the new process's mm.  	 */ -	ret = get_user_pages_remote(current, bprm->mm, pos, 1, gup_flags, +	ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,  			&page, NULL, NULL);  	if (ret <= 0)  		return NULL; @@ -909,11 +911,14 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)  	if (IS_ERR(file))  		goto out; +	/* +	 * may_open() has already checked for this, so it should be +	 * impossible to trip now. But we need to be extra cautious +	 * and check again at the very end too. +	 */  	err = -EACCES; -	if (!S_ISREG(file_inode(file)->i_mode)) -		goto exit; - -	if (path_noexec(&file->f_path)) +	if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode) || +			 path_noexec(&file->f_path)))  		goto exit;  	err = deny_write_access(file); @@ -1402,7 +1407,12 @@ int begin_new_exec(struct linux_binprm * bprm)  	if (retval)  		goto out_unlock; -	set_fs(USER_DS); +	/* +	 * Ensure that the uaccess routines can actually operate on userspace +	 * pointers: +	 */ +	force_uaccess_begin(); +  	me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |  					PF_NOFREEZE | PF_NO_SETAFFINITY);  	flush_thread();  |