[fish/f20] Fix CVE-2014-2905 and CVE-2014-2906

amluto amluto at fedoraproject.org
Mon Apr 28 16:56:57 UTC 2014


commit 8e15cc337d5450ce47c36fc71e8c1c65bc9016f4
Author: Andy Lutomirski <luto at amacapital.net>
Date:   Mon Apr 28 09:56:28 2014 -0700

    Fix CVE-2014-2905 and CVE-2014-2906

 fish-upstream-CVE-2014-2905.patch |  266 +++++++++++++++++++++++++++++++++++++
 fish-upstream-CVE-2014-2906.patch |   70 ++++++++++
 fish.spec                         |   10 ++-
 3 files changed, 345 insertions(+), 1 deletions(-)
---
diff --git a/fish-upstream-CVE-2014-2905.patch b/fish-upstream-CVE-2014-2905.patch
new file mode 100644
index 0000000..5a7bb2d
--- /dev/null
+++ b/fish-upstream-CVE-2014-2905.patch
@@ -0,0 +1,266 @@
+From 8412c867a501e3a68e55fef6215e86d3ac9f617b Mon Sep 17 00:00:00 2001
+Message-Id: <8412c867a501e3a68e55fef6215e86d3ac9f617b.1398703637.git.luto at amacapital.net>
+In-Reply-To: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto at amacapital.net>
+References: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto at amacapital.net>
+From: David Adam <zanchey at ucc.gu.uwa.edu.au>
+Date: Sun, 20 Apr 2014 17:51:27 +0800
+Subject: [PATCH 3/4] Check effective credentials of socket peers
+
+Fix for CVE-2014-2905.
+
+Code for getpeereid() on non-BSD systems imported from the PostgreSQL
+project under a BSD-style license.
+---
+ configure.ac        |  4 +--
+ doc_src/license.hdr | 30 +++++++++++++++++++-
+ env_universal.cpp   |  9 ++++++
+ fallback.cpp        | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ fallback.h          |  4 +++
+ fishd.cpp           |  9 +++++-
+ osx/config.h        |  6 ++++
+ 7 files changed, 137 insertions(+), 5 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index ea7c592..bdfa5f0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -557,7 +557,7 @@ LIBS=$LIBS_COMMON
+ # Check presense of various header files
+ #
+ 
+-AC_CHECK_HEADERS([getopt.h termios.h sys/resource.h term.h ncurses/term.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h execinfo.h spawn.h sys/sysctl.h])
++AC_CHECK_HEADERS([getopt.h termios.h sys/resource.h term.h ncurses/term.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h execinfo.h spawn.h sys/sysctl.h sys/un.h sys/ucred.h ucred.h ])
+ 
+ if test x$local_gettext != xno; then
+   AC_CHECK_HEADERS([libintl.h])
+@@ -698,7 +698,7 @@ fi
+ AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
+ AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc )
+ AC_CHECK_FUNCS( wcstol wcslcat wcslcpy lrand48_r killpg )
+-AC_CHECK_FUNCS( backtrace backtrace_symbols sysconf getifaddrs )
++AC_CHECK_FUNCS( backtrace backtrace_symbols sysconf getifaddrs getpeerucred getpeereid )
+ 
+ if test x$local_gettext != xno; then
+   AC_CHECK_FUNCS( gettext dcgettext )
+diff --git a/doc_src/license.hdr b/doc_src/license.hdr
+index 64bab10..f292722 100644
+--- a/doc_src/license.hdr
++++ b/doc_src/license.hdr
+@@ -1400,6 +1400,34 @@ POSSIBILITY OF SUCH DAMAGES.
+ 
+ <P>
+ 
+-*/
++<hr>
++
++<h2>License for getpeereid</h2>
++
++\c fish contains code imported from the PostgreSQL project under
++license, namely the getpeereid fallback function. This code is copyrighted
++by:
++
++Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
++
++Portions Copyright (c) 1994, The Regents of the University of California
++
++Permission to use, copy, modify, and distribute this software and its
++documentation for any purpose, without fee, and without a written agreement
++is hereby granted, provided that the above copyright notice and this
++paragraph and the following two paragraphs appear in all copies.
++
++IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
++DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
++LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
++DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
++POSSIBILITY OF SUCH DAMAGE.
++
++THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
++INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
++AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
++ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
++PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ 
+ \htmlonly </div> \endhtmlonly
++*/
+diff --git a/env_universal.cpp b/env_universal.cpp
+index c7d060a..987f88b 100644
+--- a/env_universal.cpp
++++ b/env_universal.cpp
+@@ -88,6 +88,8 @@ static int try_get_socket_once(void)
+ 
+     wdir = path;
+     wuname = user;
++    uid_t seuid;
++    gid_t segid;
+ 
+     if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+     {
+@@ -135,6 +137,13 @@ static int try_get_socket_once(void)
+         return -1;
+     }
+ 
++    if ((getpeereid(s, &seuid, &segid) != 0) || seuid != geteuid())
++    {
++        debug(1, L"Wrong credentials for socket %s at fd %d", name.c_str(), s);
++        close(s);
++        return -1;
++    }
++
+     if ((make_fd_nonblocking(s) != 0) || (fcntl(s, F_SETFD, FD_CLOEXEC) != 0))
+     {
+         wperror(L"fcntl");
+diff --git a/fallback.cpp b/fallback.cpp
+index 5e4b3e1..34db397 100644
+--- a/fallback.cpp
++++ b/fallback.cpp
+@@ -15,8 +15,9 @@
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <sys/types.h>
++#include <sys/socket.h>
+ #include <sys/stat.h>
+-#include <unistd.h>
++#include <sys/param.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <wchar.h>
+@@ -1521,3 +1522,80 @@ static int mk_wcswidth(const wchar_t *pwcs, size_t n)
+ }
+ 
+ #endif // HAVE_BROKEN_WCWIDTH
++
++#ifndef HAVE_GETPEEREID
++
++/*-------------------------------------------------------------------------
++ *
++ * getpeereid.c
++ *		get peer userid for UNIX-domain socket connection
++ *
++ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
++ *
++ *
++ * IDENTIFICATION
++ *	  src/port/getpeereid.c
++ *
++ *-------------------------------------------------------------------------
++ */
++
++#ifdef HAVE_SYS_UN_H
++#include <sys/un.h>
++#endif
++#ifdef HAVE_UCRED_H
++#include <ucred.h>
++#endif
++#ifdef HAVE_SYS_UCRED_H
++#include <sys/ucred.h>
++#endif
++
++/*
++ * BSD-style getpeereid() for platforms that lack it.
++ */
++int getpeereid(int sock, uid_t *uid, gid_t *gid)
++{
++#if defined(SO_PEERCRED)
++	/* Linux: use getsockopt(SO_PEERCRED) */
++	struct ucred peercred;
++	socklen_t so_len = sizeof(peercred);
++
++	if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
++		so_len != sizeof(peercred))
++		return -1;
++	*uid = peercred.uid;
++	*gid = peercred.gid;
++	return 0;
++#elif defined(LOCAL_PEERCRED)
++	/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
++	struct xucred peercred;
++	socklen_t * so_len = sizeof(peercred);
++
++	if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
++		so_len != sizeof(peercred) ||
++		peercred.cr_version != XUCRED_VERSION)
++		return -1;
++	*uid = peercred.cr_uid;
++	*gid = peercred.cr_gid;
++	return 0;
++#elif defined(HAVE_GETPEERUCRED)
++	/* Solaris: use getpeerucred() */
++	ucred_t    *ucred;
++
++	ucred = NULL;				/* must be initialized to NULL */
++	if (getpeerucred(sock, &ucred) == -1)
++		return -1;
++
++	*uid = ucred_geteuid(ucred);
++	*gid = ucred_getegid(ucred);
++	ucred_free(ucred);
++
++	if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
++		return -1;
++	return 0;
++#else
++	/* No implementation available on this platform */
++	errno = ENOSYS;
++	return -1;
++#endif
++}
++#endif // HAVE_GETPEEREID
+diff --git a/fallback.h b/fallback.h
+index eba91be..6898ea5 100644
+--- a/fallback.h
++++ b/fallback.h
+@@ -482,3 +482,7 @@ double nan(char *tagp);
+ 
+ 
+ #endif
++
++#ifndef HAVE_GETPEEREID
++int getpeereid(int sock, uid_t *uid, gid_t *gid);
++#endif
+diff --git a/fishd.cpp b/fishd.cpp
+index edb79c2..1e09524 100644
+--- a/fishd.cpp
++++ b/fishd.cpp
+@@ -880,6 +880,8 @@ int main(int argc, char ** argv)
+     int child_socket;
+     struct sockaddr_un remote;
+     socklen_t t;
++    uid_t sock_euid;
++    gid_t sock_egid;
+     int max_fd;
+     int update_count=0;
+ 
+@@ -1000,7 +1002,12 @@ int main(int argc, char ** argv)
+             {
+                 debug(4, L"Connected with new child on fd %d", child_socket);
+ 
+-                if (make_fd_nonblocking(child_socket) != 0)
++                if (((getpeereid(child_socket, &sock_euid, &sock_egid) != 0) || sock_euid != geteuid()))
++                {
++                    debug(1, L"Wrong credentials for child on fd %d", child_socket);
++                    close(child_socket);
++                }
++                else if (make_fd_nonblocking(child_socket) != 0)
+                 {
+                     wperror(L"fcntl");
+                     close(child_socket);
+diff --git a/osx/config.h b/osx/config.h
+index 4968a78..bc058ae 100644
+--- a/osx/config.h
++++ b/osx/config.h
+@@ -40,6 +40,12 @@
+ /* Define to 1 if you have the <getopt.h> header file. */
+ #define HAVE_GETOPT_H 1
+ 
++/* Define to 1 if you have the `getpeereid' function. */
++#define HAVE_GETPEEREID 1
++
++/* Define to 1 if you have the `getpeerucred' function. */
++/* #undef HAVE_GETPEERUCRED */
++
+ /* Define to 1 if you have the `gettext' function. */
+ /* #undef HAVE_GETTEXT */
+ 
+-- 
+1.9.0
+
diff --git a/fish-upstream-CVE-2014-2906.patch b/fish-upstream-CVE-2014-2906.patch
new file mode 100644
index 0000000..ae99537
--- /dev/null
+++ b/fish-upstream-CVE-2014-2906.patch
@@ -0,0 +1,70 @@
+From c0989dce2d882c94eb3183e7b94402ba53534abb Mon Sep 17 00:00:00 2001
+Message-Id: <c0989dce2d882c94eb3183e7b94402ba53534abb.1398703637.git.luto at amacapital.net>
+In-Reply-To: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto at amacapital.net>
+References: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto at amacapital.net>
+From: David Adam <zanchey at ucc.gu.uwa.edu.au>
+Date: Sun, 20 Apr 2014 23:51:20 +0800
+Subject: [PATCH 4/4] use mktemp(1) to generate temporary file names
+
+Fix for CVE-2014-2906.
+
+Closes a race condition in funced which would allow execution of
+arbitrary code; closes a race condition in psub which would allow
+alternation of the data stream.
+
+Note that `psub -f` does not work (#1040); a fix should be committed
+separately for ease of maintenance.
+---
+ share/functions/funced.fish |  6 +-----
+ share/functions/psub.fish   | 11 +++--------
+ 2 files changed, 4 insertions(+), 13 deletions(-)
+
+diff --git a/share/functions/funced.fish b/share/functions/funced.fish
+index 3c2de06..ca2e277 100644
+--- a/share/functions/funced.fish
++++ b/share/functions/funced.fish
+@@ -81,11 +81,7 @@ function funced --description 'Edit function definition'
+         return 0
+     end
+ 
+-    set -q TMPDIR; or set -l TMPDIR /tmp
+-    set -l tmpname (printf "$TMPDIR/fish_funced_%d_%d.fish" %self (random))
+-    while test -f $tmpname
+-        set tmpname (printf "$TMPDIR/fish_funced_%d_%d.fish" %self (random))
+-    end
++    set tmpname (mktemp -t fish_funced.XXXXXXXXXX)
+ 
+     if functions -q -- $funcname
+         functions -- $funcname > $tmpname
+diff --git a/share/functions/psub.fish b/share/functions/psub.fish
+index 42e34c7..7877aa4 100644
+--- a/share/functions/psub.fish
++++ b/share/functions/psub.fish
+@@ -45,21 +45,16 @@ function psub --description "Read from stdin into a file and output the filename
+ 		return
+ 	end
+ 
+-	# Find unique file name for writing output to
+-	while true
+-		set filename /tmp/.psub.(echo %self).(random);
+-		if not test -e $filename
+-			break;
+-		end
+-	end
+-
+ 	if test use_fifo = 1
+ 		# Write output to pipe. This needs to be done in the background so
+ 		# that the command substitution exits without needing to wait for
+ 		# all the commands to exit
++                set dir (mktemp -d /tmp/.psub.XXXXXXXXXX); or return
++                set filename $dir/psub.fifo
+ 		mkfifo $filename
+ 		cat >$filename &
+ 	else
++                set filename (mktemp /tmp/.psub.XXXXXXXXXX)
+ 		cat >$filename
+ 	end
+ 
+-- 
+1.9.0
+
diff --git a/fish.spec b/fish.spec
index dd1d4c1..c7556df 100644
--- a/fish.spec
+++ b/fish.spec
@@ -1,6 +1,6 @@
 Name:                   fish
 Version:                2.1.0
-Release:                6%{?dist}
+Release:                7%{?dist}
 Summary:                A friendly interactive shell
 
 Group:                  System Environment/Shells
@@ -10,6 +10,8 @@ Source0:                http://fishshell.com/files/%{version}/fish-%{version}.ta
 Patch0:                 fish-remove-usr-local.patch
 Patch1:                 fish-add-link-cxxflags.patch
 Patch2:                 fish-use-usrbinpython.patch
+Patch3:                 fish-upstream-CVE-2014-2905.patch
+Patch4:                 fish-upstream-CVE-2014-2906.patch
 
 BuildRequires:          ncurses-devel gettext groff doxygen
 
@@ -25,6 +27,8 @@ nothing to learn or configure.
 %patch0 -p1
 %patch1 -p1
 %patch2 -p1
+%patch3 -p1
+%patch4 -p1
 
 # This is unused.  If we fiddle with Python versions, its presence will
 # be confusing.
@@ -77,6 +81,10 @@ fi
 
 
 %changelog
+* Mon Apr 28 2014 Andy Lutomirski <luto at mit.edu> - 2.1.0-7
+- Fix CVE-2014-2905
+- Fix CVE-2014-2906
+
 * Fri Dec 20 2013 Andy Lutomirski <luto at mit.edu> - 2.1.0-6
 - Switch back to Python 2
 


More information about the scm-commits mailing list