From 8e15cc337d5450ce47c36fc71e8c1c65bc9016f4 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Apr 28 2014 16:56:28 +0000 Subject: Fix CVE-2014-2905 and CVE-2014-2906 --- 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@amacapital.net> +In-Reply-To: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto@amacapital.net> +References: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto@amacapital.net> +From: David Adam +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. + +

+ +-*/ ++


++ ++

License for getpeereid

++ ++\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 \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 + #include + #include ++#include + #include +-#include ++#include + #include + #include + #include +@@ -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 ++#endif ++#ifdef HAVE_UCRED_H ++#include ++#endif ++#ifdef HAVE_SYS_UCRED_H ++#include ++#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 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: +In-Reply-To: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto@amacapital.net> +References: <3c5d5b344ee945b99e4bb16a44af6f293601813d.1398703637.git.luto@amacapital.net> +From: David Adam +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 - 2.1.0-7 +- Fix CVE-2014-2905 +- Fix CVE-2014-2906 + * Fri Dec 20 2013 Andy Lutomirski - 2.1.0-6 - Switch back to Python 2