diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 8 | 
1 files changed, 7 insertions, 1 deletions
| diff --git a/fs/exec.c b/fs/exec.c index a126e3d1cacb..50e76cc633c4 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1692,6 +1692,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)  	unsigned int mode;  	vfsuid_t vfsuid;  	vfsgid_t vfsgid; +	int err;  	if (!mnt_may_suid(file->f_path.mnt))  		return; @@ -1708,12 +1709,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)  	/* Be careful if suid/sgid is set */  	inode_lock(inode); -	/* reload atomically mode/uid/gid now that lock held */ +	/* Atomically reload and check mode/uid/gid now that lock held. */  	mode = inode->i_mode;  	vfsuid = i_uid_into_vfsuid(idmap, inode);  	vfsgid = i_gid_into_vfsgid(idmap, inode); +	err = inode_permission(idmap, inode, MAY_EXEC);  	inode_unlock(inode); +	/* Did the exec bit vanish out from under us? Give up. */ +	if (err) +		return; +  	/* We ignore suid/sgid if there are no mappings for them in the ns */  	if (!vfsuid_has_mapping(bprm->cred->user_ns, vfsuid) ||  	    !vfsgid_has_mapping(bprm->cred->user_ns, vfsgid)) | 
