Revert "fs: take i_mutex during prepare_binprm for set[ug]id executables"
This reverts commit 70fd3becfdb9015b9b3c6c02fbf67eb4e7072d95.
diff --git a/fs/exec.c b/fs/exec.c
index d55c436..0ea0b4c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1286,45 +1286,6 @@
return res;
}
-static void bprm_fill_uid(struct linux_binprm *bprm)
-{
- struct inode *inode;
- unsigned int mode;
- uid_t uid;
- gid_t gid;
-
- /* clear any previous set[ug]id data from a previous binary */
- bprm->cred->euid = current_euid();
- bprm->cred->egid = current_egid();
-
- if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
- return;
-
- inode = bprm->file->f_path.dentry->d_inode;
- mode = ACCESS_ONCE(inode->i_mode);
- if (!(mode & (S_ISUID|S_ISGID)))
- return;
-
- /* Be careful if suid/sgid is set */
- mutex_lock(&inode->i_mutex);
-
- /* reload atomically mode/uid/gid now that lock held */
- mode = inode->i_mode;
- uid = inode->i_uid;
- gid = inode->i_gid;
- mutex_unlock(&inode->i_mutex);
-
- if (mode & S_ISUID) {
- bprm->per_clear |= PER_CLEAR_ON_SETID;
- bprm->cred->euid = uid;
- }
-
- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
- bprm->per_clear |= PER_CLEAR_ON_SETID;
- bprm->cred->egid = gid;
- }
-}
-
/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -1333,12 +1294,36 @@
*/
int prepare_binprm(struct linux_binprm *bprm)
{
+ umode_t mode;
+ struct inode * inode = bprm->file->f_path.dentry->d_inode;
int retval;
+ mode = inode->i_mode;
if (bprm->file->f_op == NULL)
return -EACCES;
- bprm_fill_uid(bprm);
+ /* clear any previous set[ug]id data from a previous binary */
+ bprm->cred->euid = current_euid();
+ bprm->cred->egid = current_egid();
+
+ if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
+ /* Set-uid? */
+ if (mode & S_ISUID) {
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->euid = inode->i_uid;
+ }
+
+ /* Set-gid? */
+ /*
+ * If setgid is set but no group execute bit then this
+ * is a candidate for mandatory locking, not a setgid
+ * executable.
+ */
+ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+ bprm->cred->egid = inode->i_gid;
+ }
+ }
/* fill in binprm security blob */
retval = security_bprm_set_creds(bprm);