summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Kuster <akuster@mvista.com>2016-02-05 16:57:11 (GMT)
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-03-03 11:11:40 (GMT)
commit8ca73f8fa4ff7f9edb101ee563e5547d3edc46cb (patch)
treefb0793c4ed8839c18631a71e75d2e8a20daccd93
parentd25973e203b8298005389983bf17f613c940c40e (diff)
downloadpoky-8ca73f8fa4ff7f9edb101ee563e5547d3edc46cb.tar.gz
curl: Security fix CVE-2016-0754
CVE-2016-0754 curl: remote file name path traversal in curl tool for Windows (From OE-Core master rev: b2c9b48dea2fd968c307a809ff95f2e686435222) minor tweak to tool_operate.c to get it to apply (From OE-Core rev: b8df558ece47e51653e1fc0fb0637ec2cdf2907b) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Joshua Lock <joshua.g.lock@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-support/curl/curl/CVE-2016-0754.patch384
-rw-r--r--meta/recipes-support/curl/curl_7.40.0.bb3
2 files changed, 386 insertions, 1 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2016-0754.patch b/meta/recipes-support/curl/curl/CVE-2016-0754.patch
new file mode 100644
index 0000000..b4683f4
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2016-0754.patch
@@ -0,0 +1,384 @@
1From b1bb4ca6d8777683b6a549fb61dba36759da26f4 Mon Sep 17 00:00:00 2001
2From: Ray Satiro <raysatiro@yahoo.com>
3Date: Tue, 26 Jan 2016 23:23:15 +0100
4Subject: [PATCH] curl: avoid local drive traversal when saving file (Windows)
5
6curl does not sanitize colons in a remote file name that is used as the
7local file name. This may lead to a vulnerability on systems where the
8colon is a special path character. Currently Windows/DOS is the only OS
9where this vulnerability applies.
10
11CVE-2016-0754
12
13Bug: http://curl.haxx.se/docs/adv_20160127B.html
14
15Upstream-Status: Backport
16http://curl.haxx.se/CVE-2016-0754.patch
17
18CVE: CVE-2016-0754
19Signed-off-by: Armin Kuster <akuster@mvista.com>
20
21---
22 src/tool_cb_hdr.c | 40 ++++++------
23 src/tool_doswin.c | 174 ++++++++++++++++++++++++++++++++++++++++++++---------
24 src/tool_doswin.h | 2 +-
25 src/tool_operate.c | 29 ++++++---
26 4 files changed, 187 insertions(+), 58 deletions(-)
27
28Index: curl-7.40.0/src/tool_cb_hdr.c
29===================================================================
30--- curl-7.40.0.orig/src/tool_cb_hdr.c
31+++ curl-7.40.0/src/tool_cb_hdr.c
32@@ -28,6 +28,7 @@
33 #include "curlx.h"
34
35 #include "tool_cfgable.h"
36+#include "tool_doswin.h"
37 #include "tool_msgs.h"
38 #include "tool_cb_hdr.h"
39
40@@ -111,18 +112,24 @@ size_t tool_header_cb(void *ptr, size_t
41 */
42 len = (ssize_t)cb - (p - str);
43 filename = parse_filename(p, len);
44- if(filename) {
45- outs->filename = filename;
46- outs->alloc_filename = TRUE;
47- outs->is_cd_filename = TRUE;
48- outs->s_isreg = TRUE;
49- outs->fopened = FALSE;
50- outs->stream = NULL;
51- hdrcbdata->honor_cd_filename = FALSE;
52- break;
53- }
54- else
55+ if(!filename)
56+ return failure;
57+
58+#if defined(MSDOS) || defined(WIN32)
59+ if(sanitize_file_name(&filename)) {
60+ free(filename);
61 return failure;
62+ }
63+#endif /* MSDOS || WIN32 */
64+
65+ outs->filename = filename;
66+ outs->alloc_filename = TRUE;
67+ outs->is_cd_filename = TRUE;
68+ outs->s_isreg = TRUE;
69+ outs->fopened = FALSE;
70+ outs->stream = NULL;
71+ hdrcbdata->honor_cd_filename = FALSE;
72+ break;
73 }
74 }
75
76@@ -178,15 +185,12 @@ static char *parse_filename(const char *
77 }
78
79 /* scan for the end letter and stop there */
80- q = p;
81- while(*q) {
82- if(q[1] && (q[0] == '\\'))
83- q++;
84- else if(q[0] == stop)
85+ for(q = p; *q; ++q) {
86+ if(*q == stop) {
87+ *q = '\0';
88 break;
89- q++;
90+ }
91 }
92- *q = '\0';
93
94 /* make sure the file name doesn't end in \r or \n */
95 q = strchr(p, '\r');
96Index: curl-7.40.0/src/tool_doswin.c
97===================================================================
98--- curl-7.40.0.orig/src/tool_doswin.c
99+++ curl-7.40.0/src/tool_doswin.c
100@@ -85,42 +85,106 @@ __pragma(warning(pop))
101 # include <fcntl.h> /* _use_lfn(f) prototype */
102 #endif
103
104-static const char *msdosify (const char *file_name);
105-static char *rename_if_dos_device_name (char *file_name);
106+static char *msdosify(const char *file_name);
107+static char *rename_if_dos_device_name(const char *file_name);
108
109-/*
110- * sanitize_dos_name: returns a newly allocated string holding a
111- * valid file name which will be a transformation of given argument
112- * in case this wasn't already a valid file name.
113- *
114- * This function takes ownership of given argument, free'ing it before
115- * returning. Caller is responsible of free'ing returned string. Upon
116- * out of memory condition function returns NULL.
117- */
118
119-char *sanitize_dos_name(char *file_name)
120+/*
121+Sanitize *file_name.
122+Success: (CURLE_OK) *file_name points to a sanitized version of the original.
123+ This function takes ownership of the original *file_name and frees it.
124+Failure: (!= CURLE_OK) *file_name is unchanged.
125+*/
126+CURLcode sanitize_file_name(char **file_name)
127 {
128- char new_name[PATH_MAX];
129+ size_t len;
130+ char *p, *sanitized;
131+
132+ /* Calculate the maximum length of a filename.
133+ FILENAME_MAX is often the same as PATH_MAX, in other words it does not
134+ discount the path information. PATH_MAX size is calculated based on:
135+ <drive-letter><colon><path-sep><max-filename-len><NULL> */
136+ const size_t max_filename_len = PATH_MAX - 3 - 1;
137+
138+ if(!file_name || !*file_name)
139+ return CURLE_BAD_FUNCTION_ARGUMENT;
140+
141+ len = strlen(*file_name);
142+
143+ if(len >= max_filename_len)
144+ len = max_filename_len - 1;
145+
146+ sanitized = malloc(len + 1);
147
148- if(!file_name)
149- return NULL;
150+ if(!sanitized)
151+ return CURLE_OUT_OF_MEMORY;
152
153- if(strlen(file_name) >= PATH_MAX)
154- file_name[PATH_MAX-1] = '\0'; /* truncate it */
155+ strncpy(sanitized, *file_name, len);
156+ sanitized[len] = '\0';
157
158- strcpy(new_name, msdosify(file_name));
159+ for(p = sanitized; *p; ++p ) {
160+ const char *banned;
161+ if(1 <= *p && *p <= 31) {
162+ *p = '_';
163+ continue;
164+ }
165+ for(banned = "|<>/\\\":?*"; *banned; ++banned) {
166+ if(*p == *banned) {
167+ *p = '_';
168+ break;
169+ }
170+ }
171+ }
172
173- Curl_safefree(file_name);
174+#ifdef MSDOS
175+ /* msdosify checks for more banned characters for MSDOS, however it allows
176+ for some path information to pass through. since we are sanitizing only a
177+ filename and cannot allow a path it's important this call be done in
178+ addition to and not instead of the banned character check above. */
179+ p = msdosify(sanitized);
180+ if(!p) {
181+ free(sanitized);
182+ return CURLE_BAD_FUNCTION_ARGUMENT;
183+ }
184+ sanitized = p;
185+ len = strlen(sanitized);
186+#endif
187+
188+ p = rename_if_dos_device_name(sanitized);
189+ if(!p) {
190+ free(sanitized);
191+ return CURLE_BAD_FUNCTION_ARGUMENT;
192+ }
193+ sanitized = p;
194+ len = strlen(sanitized);
195
196- return strdup(rename_if_dos_device_name(new_name));
197+ /* dos_device_name rename will rename a device name, possibly changing the
198+ length. If the length is too long now we can't truncate it because we
199+ could end up with a device name. In practice this shouldn't be a problem
200+ because device names are short, but you never know. */
201+ if(len >= max_filename_len) {
202+ free(sanitized);
203+ return CURLE_BAD_FUNCTION_ARGUMENT;
204+ }
205+
206+ *file_name = sanitized;
207+ return CURLE_OK;
208 }
209
210-/* The following functions are taken with modification from the DJGPP
211- * port of tar 1.12. They use algorithms originally from DJTAR. */
212+/* The functions msdosify, rename_if_dos_device_name and __crt0_glob_function
213+ * were taken with modification from the DJGPP port of tar 1.12. They use
214+ * algorithms originally from DJTAR.
215+ */
216
217-static const char *msdosify (const char *file_name)
218+/*
219+Extra sanitization MSDOS for file_name.
220+Returns a copy of file_name that is sanitized by MSDOS standards.
221+Warning: path information may pass through. For sanitizing a filename use
222+sanitize_file_name which calls this function after sanitizing path info.
223+*/
224+static char *msdosify(const char *file_name)
225 {
226- static char dos_name[PATH_MAX];
227+ char dos_name[PATH_MAX];
228 static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */
229 "|<>\\\":?*"; /* illegal in DOS & W95 */
230 static const char *illegal_chars_w95 = &illegal_chars_dos[8];
231@@ -201,15 +265,20 @@ static const char *msdosify (const char
232 }
233
234 *d = '\0';
235- return dos_name;
236+ return strdup(dos_name);
237 }
238
239-static char *rename_if_dos_device_name (char *file_name)
240+/*
241+Rename file_name if it's a representation of a device name.
242+Returns a copy of file_name, and the copy will have contents different from the
243+original if a device name was found.
244+*/
245+static char *rename_if_dos_device_name(const char *file_name)
246 {
247 /* We could have a file whose name is a device on MS-DOS. Trying to
248 * retrieve such a file would fail at best and wedge us at worst. We need
249 * to rename such files. */
250- char *base;
251+ char *p, *base;
252 struct_stat st_buf;
253 char fname[PATH_MAX];
254
255@@ -219,7 +288,7 @@ static char *rename_if_dos_device_name (
256 if(((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) {
257 size_t blen = strlen(base);
258
259- if(strlen(fname) >= PATH_MAX-1) {
260+ if(strlen(fname) == PATH_MAX-1) {
261 /* Make room for the '_' */
262 blen--;
263 base[blen] = '\0';
264@@ -227,9 +296,54 @@ static char *rename_if_dos_device_name (
265 /* Prepend a '_'. */
266 memmove(base + 1, base, blen + 1);
267 base[0] = '_';
268- strcpy(file_name, fname);
269 }
270- return file_name;
271+
272+ /* The above stat check does not identify devices for me in Windows 7. For
273+ example a stat on COM1 returns a regular file S_IFREG. According to MSDN
274+ stat doc that is the correct behavior, so I assume the above code is
275+ legacy, maybe MSDOS or DJGPP specific? */
276+
277+ /* Rename devices.
278+ Examples: CON => _CON, CON.EXT => CON_EXT, CON:ADS => CON_ADS */
279+ for(p = fname; p; p = (p == fname && fname != base ? base : NULL)) {
280+ size_t p_len;
281+ int x = (curl_strnequal(p, "CON", 3) ||
282+ curl_strnequal(p, "PRN", 3) ||
283+ curl_strnequal(p, "AUX", 3) ||
284+ curl_strnequal(p, "NUL", 3)) ? 3 :
285+ (curl_strnequal(p, "CLOCK$", 6)) ? 6 :
286+ (curl_strnequal(p, "COM", 3) || curl_strnequal(p, "LPT", 3)) ?
287+ (('1' <= p[3] && p[3] <= '9') ? 4 : 3) : 0;
288+
289+ if(!x)
290+ continue;
291+
292+ /* the devices may be accessible with an extension or ADS, for
293+ example CON.AIR and CON:AIR both access console */
294+ if(p[x] == '.' || p[x] == ':') {
295+ p[x] = '_';
296+ continue;
297+ }
298+ else if(p[x]) /* no match */
299+ continue;
300+
301+ p_len = strlen(p);
302+
303+ if(strlen(fname) == PATH_MAX-1) {
304+ /* Make room for the '_' */
305+ p_len--;
306+ p[p_len] = '\0';
307+ }
308+ /* Prepend a '_'. */
309+ memmove(p + 1, p, p_len + 1);
310+ p[0] = '_';
311+
312+ /* if fname was just modified then the basename pointer must be updated */
313+ if(p == fname)
314+ base = basename(fname);
315+ }
316+
317+ return strdup(fname);
318 }
319
320 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
321Index: curl-7.40.0/src/tool_doswin.h
322===================================================================
323--- curl-7.40.0.orig/src/tool_doswin.h
324+++ curl-7.40.0/src/tool_doswin.h
325@@ -25,7 +25,7 @@
326
327 #if defined(MSDOS) || defined(WIN32)
328
329-char *sanitize_dos_name(char *file_name);
330+CURLcode sanitize_file_name(char **filename);
331
332 #if defined(MSDOS) && (defined(__DJGPP__) || defined(__GO32__))
333
334Index: curl-7.40.0/src/tool_operate.c
335===================================================================
336--- curl-7.40.0.orig/src/tool_operate.c
337+++ curl-7.40.0/src/tool_operate.c
338@@ -543,26 +543,37 @@ static CURLcode operate_do(struct Global
339 result = get_url_file_name(&outfile, this_url);
340 if(result)
341 goto show_error;
342+
343+#if defined(MSDOS) || defined(WIN32)
344+ result = sanitize_file_name(&outfile);
345+ if(result) {
346+ Curl_safefree(outfile);
347+ goto show_error;
348+ }
349+#endif /* MSDOS || WIN32 */
350+
351 if(!*outfile && !config->content_disposition) {
352 helpf(global->errors, "Remote file name has no length!\n");
353 result = CURLE_WRITE_ERROR;
354 goto quit_urls;
355 }
356-#if defined(MSDOS) || defined(WIN32)
357- /* For DOS and WIN32, we do some major replacing of
358- bad characters in the file name before using it */
359- outfile = sanitize_dos_name(outfile);
360- if(!outfile) {
361- result = CURLE_OUT_OF_MEMORY;
362- goto show_error;
363- }
364-#endif /* MSDOS || WIN32 */
365 }
366 else if(urls) {
367 /* fill '#1' ... '#9' terms from URL pattern */
368 char *storefile = outfile;
369 result = glob_match_url(&outfile, storefile, urls);
370 Curl_safefree(storefile);
371+
372+#if defined(MSDOS) || defined(WIN32)
373+ if(!result) {
374+ result = sanitize_file_name(&outfile);
375+ if(result) {
376+ Curl_safefree(outfile);
377+ goto show_error;
378+ }
379+ }
380+#endif /* MSDOS || WIN32 */
381+
382 if(result) {
383 /* bad globbing */
384 warnf(config, "bad output glob!\n");
diff --git a/meta/recipes-support/curl/curl_7.40.0.bb b/meta/recipes-support/curl/curl_7.40.0.bb
index e6a6a42..01c201e 100644
--- a/meta/recipes-support/curl/curl_7.40.0.bb
+++ b/meta/recipes-support/curl/curl_7.40.0.bb
@@ -16,7 +16,8 @@ SRC_URI = "http://curl.haxx.se/download/curl-${PV}.tar.bz2 \
16# curl likes to set -g0 in CFLAGS, so we stop it 16# curl likes to set -g0 in CFLAGS, so we stop it
17# from mucking around with debug options 17# from mucking around with debug options
18# 18#
19SRC_URI += " file://configure_ac.patch" 19SRC_URI += " file://configure_ac.patch \
20 file://CVE-2016-0754.patch"
20 21
21SRC_URI[md5sum] = "8d30594212e65657a5c32030f0998fa9" 22SRC_URI[md5sum] = "8d30594212e65657a5c32030f0998fa9"
22SRC_URI[sha256sum] = "899109eb3900fa6b8a2f995df7f449964292776a04763e94fae640700f883fba" 23SRC_URI[sha256sum] = "899109eb3900fa6b8a2f995df7f449964292776a04763e94fae640700f883fba"