jwboyer pushed to kernel (f22). "CVE-2015-3339 race condition between chown and execve (rhbz 1214030)"

notifications at fedoraproject.org notifications at fedoraproject.org
Fri Apr 24 16:49:28 UTC 2015


>From eff5420f79ae6ee5c95ca6033441b81cae621b1a Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer at fedoraproject.org>
Date: Fri, 24 Apr 2015 12:44:51 -0400
Subject: CVE-2015-3339 race condition between chown and execve (rhbz 1214030)


diff --git a/fs-take-i_mutex-during-prepare_binprm-for-set-ug-id-.patch b/fs-take-i_mutex-during-prepare_binprm-for-set-ug-id-.patch
new file mode 100644
index 0000000..230956f
--- /dev/null
+++ b/fs-take-i_mutex-during-prepare_binprm-for-set-ug-id-.patch
@@ -0,0 +1,116 @@
+From: Jann Horn <jann at thejh.net>
+Date: Sun, 19 Apr 2015 02:48:39 +0200
+Subject: [PATCH] fs: take i_mutex during prepare_binprm for set[ug]id
+ executables
+
+This prevents a race between chown() and execve(), where chowning a
+setuid-user binary to root would momentarily make the binary setuid
+root.
+
+This patch was mostly written by Linus Torvalds.
+
+Signed-off-by: Jann Horn <jann at thejh.net>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+---
+ fs/exec.c | 76 ++++++++++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 48 insertions(+), 28 deletions(-)
+
+diff --git a/fs/exec.c b/fs/exec.c
+index c7f9b733406d..00400cf522dc 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1265,6 +1265,53 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
+ 	spin_unlock(&p->fs->lock);
+ }
+ 
++static void bprm_fill_uid(struct linux_binprm *bprm)
++{
++	struct inode *inode;
++	unsigned int mode;
++	kuid_t uid;
++	kgid_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;
++
++	if (task_no_new_privs(current))
++		return;
++
++	inode = file_inode(bprm->file);
++	mode = READ_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);
++
++	/* 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))
++		return;
++
++	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
+@@ -1273,36 +1320,9 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
+  */
+ int prepare_binprm(struct linux_binprm *bprm)
+ {
+-	struct inode *inode = file_inode(bprm->file);
+-	umode_t mode = inode->i_mode;
+ 	int retval;
+ 
+-
+-	/* 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) &&
+-	    !task_no_new_privs(current) &&
+-	    kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) &&
+-	    kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) {
+-		/* 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;
+-		}
+-	}
++	bprm_fill_uid(bprm);
+ 
+ 	/* fill in binprm security blob */
+ 	retval = security_bprm_set_creds(bprm);
+-- 
+2.1.0
+
diff --git a/kernel.spec b/kernel.spec
index 296c6c9..6bd3b19 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -642,6 +642,9 @@ Patch26184: 0001-ALSA-hda-realtek-Support-headset-mode-for-ALC286-288.patch
 #rhbz 1208999
 Patch26177: SCSI-add-1024-max-sectors-black-list-flag.patch
 
+#CVE-2015-3330 rbhz 1214030
+Patch26188: fs-take-i_mutex-during-prepare_binprm-for-set-ug-id-.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1398,6 +1401,9 @@ ApplyPatch 0001-ALSA-hda-realtek-Support-headset-mode-for-ALC286-288.patch
 #rhbz 1208999
 ApplyPatch SCSI-add-1024-max-sectors-black-list-flag.patch
 
+#CVE-2015-3330 rbhz 1214030
+ApplyPatch fs-take-i_mutex-during-prepare_binprm-for-set-ug-id-.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2249,6 +2255,7 @@ fi
 # 
 %changelog
 * Fri Apr 24 2015 Josh Boyer <jwboyer at fedoraproject.org>
+- CVE-2015-3339 race condition between chown and execve (rhbz 1214030)
 - Fix iscsi with QNAP devices (rhbz 1208999)
 
 * Wed Apr 22 2015 Peter Robinson <pbrobinson at fedoraproject.org>
-- 
cgit v0.10.2


	http://pkgs.fedoraproject.org/cgit/kernel.git/commit/?h=f22&id=eff5420f79ae6ee5c95ca6033441b81cae621b1a


More information about the scm-commits mailing list