Blame SOURCES/0029-curl-7.29.0-CVE-2014-3707.patch

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