From 6139644280195f8fb7d59b713f3d226a84b21665 Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Tue, 8 Dec 2015 13:08:50 +0100 Subject: linux-yocto: CVE-2015-3339 Fixes race condition between chown() and execve() system calls in the linux-yocto 3.14 version. References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3339 http://seclists.org/oss-sec/2015/q2/216 Upstream fix: ihttps://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/ patch/?id=de70236fbe30749fb8c317088c16a97e700fe232 Signed-off-by: Sona Sarmadi --- recipes-kernel/linux/files/fs-CVE-2015-3339.patch | 122 ++++++++++++++++++++++ recipes-kernel/linux/linux-yocto_3.14.bbappend | 1 + 2 files changed, 123 insertions(+) create mode 100644 recipes-kernel/linux/files/fs-CVE-2015-3339.patch diff --git a/recipes-kernel/linux/files/fs-CVE-2015-3339.patch b/recipes-kernel/linux/files/fs-CVE-2015-3339.patch new file mode 100644 index 0000000..58d0f42 --- /dev/null +++ b/recipes-kernel/linux/files/fs-CVE-2015-3339.patch @@ -0,0 +1,122 @@ +Date: Sun, 19 Apr 2015 02:48:39 +0200 +Subject: fs: take i_mutex during prepare_binprm for set[ug]id executables + +commit 8b01fc86b9f425899f8a3a8fc1c47d73c2c20543 upstream. + +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. + +Fixes CVE-2015-3339. +Upstream-Status: Backport + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +Signed-off-by: Charles Williams +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sona Sarmadi +--- + fs/exec.c | 76 ++++++++++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 48 insertions(+), 28 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index ea4449d..05f1942 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1268,6 +1268,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 (current->no_new_privs) ++ return; ++ ++ inode = file_inode(bprm->file); ++ 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); ++ ++ /* 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 +@@ -1276,36 +1323,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) && +- !current->no_new_privs && +- 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); +-- +cgit v0.11.2 + diff --git a/recipes-kernel/linux/linux-yocto_3.14.bbappend b/recipes-kernel/linux/linux-yocto_3.14.bbappend index a10743c..001026f 100644 --- a/recipes-kernel/linux/linux-yocto_3.14.bbappend +++ b/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -6,4 +6,5 @@ SRC_URI += "file://HID_CVE_patches/0005-HID-steelseries-validate-output-report-d file://net-CVE-2015-2041.patch \ file://IB-uverbs-CVE-2014-8159.patch \ file://net-sctp-CVE-2015-1421.patch \ + file://fs-CVE-2015-3339.patch \ " -- cgit v1.2.3-54-g00ecf