summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 1bce1aade824..4fd9cefb56b5 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1558,6 +1558,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
unsigned int mode;
kuid_t uid;
kgid_t gid;
+ int err;
/*
* Since this can be called multiple times (via prepare_binprm),
@@ -1582,12 +1583,17 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
/* 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;
uid = inode->i_uid;
gid = inode->i_gid;
+ err = inode_permission(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 (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
!kgid_has_mapping(bprm->cred->user_ns, gid))