diff --git a/0028-curl-7.29.0-b3875606.patch b/0028-curl-7.29.0-b3875606.patch new file mode 100644 index 0000000..ddcc2bb --- /dev/null +++ b/0028-curl-7.29.0-b3875606.patch @@ -0,0 +1,271 @@ +From 45a125c1d6aaa2352c5ec04eecba322930e6d169 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 17 Oct 2014 12:59:32 +0200 +Subject: [PATCH] curl_easy_duphandle: CURLOPT_COPYPOSTFIELDS read out of + bounds + +When duplicating a handle, the data to post was duplicated using +strdup() when it could be binary and contain zeroes and it was not even +zero terminated! This caused read out of bounds crashes/segfaults. + +Bug: http://curl.haxx.se/docs/adv_20141105.html +CVE: CVE-2014-3707 +Reported-By: Symeon Paraschoudis +Upstream-commit: b3875606925536f82fc61f3114ac42f29eaf6945 +Signed-off-by: Kamil Dudka +--- + lib/formdata.c | 50 ++++++++------------------------------------------ + lib/strdup.c | 29 ++++++++++++++++++++++++++--- + lib/strdup.h | 1 + + lib/url.c | 19 +++++++++++++++---- + lib/urldata.h | 11 +++++++++-- + src/Makefile.in | 3 +-- + src/Makefile.inc | 1 - + 7 files changed, 60 insertions(+), 54 deletions(-) + +diff --git a/lib/formdata.c b/lib/formdata.c +index 3260928..050f538 100644 +--- a/lib/formdata.c ++++ b/lib/formdata.c +@@ -39,6 +39,7 @@ + #include "strequal.h" + #include "curl_memory.h" + #include "sendf.h" ++#include "strdup.h" + + #define _MPRINTF_REPLACE /* use our functions only */ + #include +@@ -216,46 +217,6 @@ static const char * ContentTypeForFilename (const char *filename, + + /*************************************************************************** + * +- * memdup() +- * +- * Copies the 'source' data to a newly allocated buffer buffer (that is +- * returned). Uses buffer_length if not null, else uses strlen to determine +- * the length of the buffer to be copied +- * +- * Returns the new pointer or NULL on failure. +- * +- ***************************************************************************/ +-static char *memdup(const char *src, size_t buffer_length) +-{ +- size_t length; +- bool add = FALSE; +- char *buffer; +- +- if(buffer_length) +- length = buffer_length; +- else if(src) { +- length = strlen(src); +- add = TRUE; +- } +- else +- /* no length and a NULL src pointer! */ +- return strdup(""); +- +- buffer = malloc(length+add); +- if(!buffer) +- return NULL; /* fail */ +- +- memcpy(buffer, src, length); +- +- /* if length unknown do null termination */ +- if(add) +- buffer[length] = '\0'; +- +- return buffer; +-} +- +-/*************************************************************************** +- * + * FormAdd() + * + * Stores a formpost parameter and builds the appropriate linked list. +@@ -684,7 +645,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, + app passed in a bad combo, so we better check for that first. */ + if(form->name) + /* copy name (without strdup; possibly contains null characters) */ +- form->name = memdup(form->name, form->namelength); ++ form->name = Curl_memdup(form->name, form->namelength? ++ form->namelength: ++ strlen(form->name)+1); ++ + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; +@@ -695,7 +659,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) ) { + /* copy value (without strdup; possibly contains null characters) */ +- form->value = memdup(form->value, form->contentslength); ++ form->value = Curl_memdup(form->value, form->contentslength? ++ form->contentslength: ++ strlen(form->value)+1); + if(!form->value) { + return_value = CURL_FORMADD_MEMORY; + break; +diff --git a/lib/strdup.c b/lib/strdup.c +index 3b776b1..14f370f 100644 +--- a/lib/strdup.c ++++ b/lib/strdup.c +@@ -19,12 +19,13 @@ + * KIND, either express or implied. + * + ***************************************************************************/ +-/* +- * This file is 'mem-include-scan' clean. See test 1132. +- */ + #include "curl_setup.h" + + #include "strdup.h" ++#include "curl_memory.h" ++ ++/* The last #include file should be: */ ++#include "memdebug.h" + + #ifndef HAVE_STRDUP + char *curlx_strdup(const char *str) +@@ -50,3 +51,25 @@ char *curlx_strdup(const char *str) + + } + #endif ++ ++/*************************************************************************** ++ * ++ * Curl_memdup(source, length) ++ * ++ * Copies the 'source' data to a newly allocated buffer (that is ++ * returned). Copies 'length' bytes. ++ * ++ * Returns the new pointer or NULL on failure. ++ * ++ ***************************************************************************/ ++char *Curl_memdup(const char *src, size_t length) ++{ ++ char *buffer = malloc(length); ++ if(!buffer) ++ return NULL; /* fail */ ++ ++ memcpy(buffer, src, length); ++ ++ /* if length unknown do null termination */ ++ return buffer; ++} +diff --git a/lib/strdup.h b/lib/strdup.h +index 49af911..36cc430 100644 +--- a/lib/strdup.h ++++ b/lib/strdup.h +@@ -26,5 +26,6 @@ + #ifndef HAVE_STRDUP + extern char *curlx_strdup(const char *str); + #endif ++char *Curl_memdup(const char *src, size_t buffer_length); + + #endif /* HEADER_CURL_STRDUP_H */ +diff --git a/lib/url.c b/lib/url.c +index b0aade1..0aa5a33 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -123,6 +123,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out); + #include "bundles.h" + #include "conncache.h" + #include "multihandle.h" ++#include "strdup.h" + + #define _MPRINTF_REPLACE /* use our functions only */ + #include +@@ -344,14 +345,24 @@ CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src) + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ +- for(i=(enum dupstring)0; i< STRING_LAST; i++) { ++ for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + r = setstropt(&dst->set.str[i], src->set.str[i]); + if(r != CURLE_OK) +- break; ++ return r; + } + +- /* If a failure occurred, freeing has to be performed externally. */ +- return r; ++ /* duplicate memory areas pointed to */ ++ i = STRING_COPYPOSTFIELDS; ++ if(src->set.postfieldsize && src->set.str[i]) { ++ /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ ++ dst->set.str[i] = Curl_memdup(src->set.str[i], src->set.postfieldsize); ++ if(!dst->set.str[i]) ++ return CURLE_OUT_OF_MEMORY; ++ /* point to the new copy */ ++ dst->set.postfields = dst->set.str[i]; ++ } ++ ++ return CURLE_OK; + } + + /* +diff --git a/lib/urldata.h b/lib/urldata.h +index 640cbb1..d03440b 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1340,7 +1340,6 @@ enum dupstring { + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ +- STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + STRING_PROXY, /* proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ +@@ -1379,7 +1378,15 @@ enum dupstring { + STRING_TLSAUTH_PASSWORD, /* TLS auth */ + #endif + +- /* -- end of strings -- */ ++ /* -- end of zero-terminated strings -- */ ++ ++ STRING_LASTZEROTERMINATED, ++ ++ /* -- below this are pointers to binary data that cannot be strdup'ed. ++ Each such pointer must be added manually to Curl_dupset() --- */ ++ ++ STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ ++ + STRING_LAST /* not used, just an end-of-list marker */ + }; + +diff --git a/src/Makefile.in b/src/Makefile.in +index 86e3d3a..74e8b9e 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -111,7 +111,7 @@ am__objects_1 = curl-tool_binmode.$(OBJEXT) curl-tool_bname.$(OBJEXT) \ + curl-tool_urlglob.$(OBJEXT) curl-tool_util.$(OBJEXT) \ + curl-tool_vms.$(OBJEXT) curl-tool_writeenv.$(OBJEXT) \ + curl-tool_writeout.$(OBJEXT) curl-tool_xattr.$(OBJEXT) +-am__objects_2 = curl-strtoofft.$(OBJEXT) curl-strdup.$(OBJEXT) \ ++am__objects_2 = curl-strtoofft.$(OBJEXT) \ + curl-rawstr.$(OBJEXT) curl-nonblock.$(OBJEXT) + am__objects_3 = + am_curl_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) +@@ -375,7 +375,6 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl -I$(top_builddir)/include \ + # the official API, but we re-use the code here to avoid duplication. + CURLX_ONES = \ + ../lib/strtoofft.c \ +- ../lib/strdup.c \ + ../lib/rawstr.c \ + ../lib/nonblock.c + +diff --git a/src/Makefile.inc b/src/Makefile.inc +index 3f9044d..ea81000 100644 +--- a/src/Makefile.inc ++++ b/src/Makefile.inc +@@ -11,7 +11,6 @@ + # the official API, but we re-use the code here to avoid duplication. + CURLX_ONES = \ + ../lib/strtoofft.c \ +- ../lib/strdup.c \ + ../lib/rawstr.c \ + ../lib/nonblock.c + +-- +2.1.0 + diff --git a/curl.spec b/curl.spec index 6dc8410..f54b785 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.29.0 -Release: 24%{?dist} +Release: 25%{?dist} License: MIT Group: Applications/Internet Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma @@ -85,6 +85,9 @@ Patch26: 0026-curl-7.29.0-CVE-2014-3620.patch # fix a connection failure when FTPS handle is reused Patch27: 0027-curl-7.29.0-0aecdf68.patch +# fix handling of CURLOPT_COPYPOSTFIELDS in curl_easy_duphandle (CVE-2014-3707) +Patch28: 0028-curl-7.29.0-b3875606.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.29.0-multilib.patch @@ -219,6 +222,7 @@ documentation of the library, too. %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 # Fedora patches %patch101 -p1 @@ -339,6 +343,9 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/aclocal/libcurl.m4 %changelog +* Wed Nov 05 2014 Kamil Dudka 7.29.0-25 +- fix handling of CURLOPT_COPYPOSTFIELDS in curl_easy_duphandle (CVE-2014-3707) + * Tue Oct 21 2014 Kamil Dudka 7.29.0-24 - fix a connection failure when FTPS handle is reused