diff options
author | Lee Chee Yang <chee.yang.lee@intel.com> | 2021-01-13 17:29:35 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-01-21 23:08:16 +0000 |
commit | d5a1834e4fb666dd2348b7dca59ab3052d25468d (patch) | |
tree | 1e75ba5a4d4c21fec0773bf7f1fa3a09dca0911d /meta/recipes-support | |
parent | 6b78a1734318fce8ee13c28c1454d3d76f52bae8 (diff) | |
download | poky-d5a1834e4fb666dd2348b7dca59ab3052d25468d.tar.gz |
curl: fix CVE-2020-8231/8284/8285/8286
backport CVE-2020-8284 fixes from upstream, but drop
binary file tests/data/test1465.
upstream fixes for CVE-2020-8231, CVE-2020-8285 and CVE-2020-8286
does not applies cleanly to 7.69.1, fedora have working patch
hence import patch from Fedora.
https://koji.fedoraproject.org/koji/rpminfo?rpmID=24270817
(From OE-Core rev: 16ec5dea53d24cc1449d173912c1056c873fa98d)
Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-support')
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8231.patch | 1092 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8284.patch | 209 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8285.patch | 260 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl/CVE-2020-8286.patch | 133 | ||||
-rw-r--r-- | meta/recipes-support/curl/curl_7.69.1.bb | 4 |
5 files changed, 1698 insertions, 0 deletions
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8231.patch b/meta/recipes-support/curl/curl/CVE-2020-8231.patch new file mode 100644 index 0000000000..51f40047f1 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2020-8231.patch | |||
@@ -0,0 +1,1092 @@ | |||
1 | From c3359693e17fccdf2a04f0b908bc8f51cdc38133 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Mon, 27 Apr 2020 00:33:21 +0200 | ||
4 | Subject: [PATCH 1/3] conncache: various concept cleanups | ||
5 | |||
6 | More connection cache accesses are protected by locks. | ||
7 | |||
8 | CONNCACHE_* is a beter prefix for the connection cache lock macros. | ||
9 | |||
10 | Curl_attach_connnection: now called as soon as there's a connection | ||
11 | struct available and before the connection is added to the connection | ||
12 | cache. | ||
13 | |||
14 | Curl_disconnect: now assumes that the connection is already removed from | ||
15 | the connection cache. | ||
16 | |||
17 | Ref: #4915 | ||
18 | Closes #5009 | ||
19 | |||
20 | Upstream-commit: c06902713998d68202c5a764de910ba8d0e8f54d | ||
21 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
22 | |||
23 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0004-curl-7.69.1-CVE-2020-8231.patch ] | ||
24 | CVE: CVE-2020-8286 | ||
25 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
26 | --- | ||
27 | lib/conncache.c | 87 ++++++++++++++++++++----------------------- | ||
28 | lib/conncache.h | 9 ++--- | ||
29 | lib/hostip.c | 12 +++--- | ||
30 | lib/http_negotiate.h | 6 ++- | ||
31 | lib/http_ntlm.h | 6 ++- | ||
32 | lib/multi.c | 56 ++++++++++++++-------------- | ||
33 | lib/multiif.h | 1 + | ||
34 | lib/url.c | 69 ++++++++++++++++++---------------- | ||
35 | tests/data/test1554 | 14 +++++++ | ||
36 | tests/unit/unit1620.c | 6 +-- | ||
37 | 10 files changed, 139 insertions(+), 127 deletions(-) | ||
38 | |||
39 | diff --git a/lib/conncache.c b/lib/conncache.c | ||
40 | index cbd3bb1..95fcea6 100644 | ||
41 | --- a/lib/conncache.c | ||
42 | +++ b/lib/conncache.c | ||
43 | @@ -49,53 +49,51 @@ static void conn_llist_dtor(void *user, void *element) | ||
44 | conn->bundle = NULL; | ||
45 | } | ||
46 | |||
47 | -static CURLcode bundle_create(struct Curl_easy *data, | ||
48 | - struct connectbundle **cb_ptr) | ||
49 | +static CURLcode bundle_create(struct connectbundle **bundlep) | ||
50 | { | ||
51 | - (void)data; | ||
52 | - DEBUGASSERT(*cb_ptr == NULL); | ||
53 | - *cb_ptr = malloc(sizeof(struct connectbundle)); | ||
54 | - if(!*cb_ptr) | ||
55 | + DEBUGASSERT(*bundlep == NULL); | ||
56 | + *bundlep = malloc(sizeof(struct connectbundle)); | ||
57 | + if(!*bundlep) | ||
58 | return CURLE_OUT_OF_MEMORY; | ||
59 | |||
60 | - (*cb_ptr)->num_connections = 0; | ||
61 | - (*cb_ptr)->multiuse = BUNDLE_UNKNOWN; | ||
62 | + (*bundlep)->num_connections = 0; | ||
63 | + (*bundlep)->multiuse = BUNDLE_UNKNOWN; | ||
64 | |||
65 | - Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); | ||
66 | + Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor); | ||
67 | return CURLE_OK; | ||
68 | } | ||
69 | |||
70 | -static void bundle_destroy(struct connectbundle *cb_ptr) | ||
71 | +static void bundle_destroy(struct connectbundle *bundle) | ||
72 | { | ||
73 | - if(!cb_ptr) | ||
74 | + if(!bundle) | ||
75 | return; | ||
76 | |||
77 | - Curl_llist_destroy(&cb_ptr->conn_list, NULL); | ||
78 | + Curl_llist_destroy(&bundle->conn_list, NULL); | ||
79 | |||
80 | - free(cb_ptr); | ||
81 | + free(bundle); | ||
82 | } | ||
83 | |||
84 | /* Add a connection to a bundle */ | ||
85 | -static void bundle_add_conn(struct connectbundle *cb_ptr, | ||
86 | +static void bundle_add_conn(struct connectbundle *bundle, | ||
87 | struct connectdata *conn) | ||
88 | { | ||
89 | - Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, | ||
90 | + Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn, | ||
91 | &conn->bundle_node); | ||
92 | - conn->bundle = cb_ptr; | ||
93 | - cb_ptr->num_connections++; | ||
94 | + conn->bundle = bundle; | ||
95 | + bundle->num_connections++; | ||
96 | } | ||
97 | |||
98 | /* Remove a connection from a bundle */ | ||
99 | -static int bundle_remove_conn(struct connectbundle *cb_ptr, | ||
100 | +static int bundle_remove_conn(struct connectbundle *bundle, | ||
101 | struct connectdata *conn) | ||
102 | { | ||
103 | struct curl_llist_element *curr; | ||
104 | |||
105 | - curr = cb_ptr->conn_list.head; | ||
106 | + curr = bundle->conn_list.head; | ||
107 | while(curr) { | ||
108 | if(curr->ptr == conn) { | ||
109 | - Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); | ||
110 | - cb_ptr->num_connections--; | ||
111 | + Curl_llist_remove(&bundle->conn_list, curr, NULL); | ||
112 | + bundle->num_connections--; | ||
113 | conn->bundle = NULL; | ||
114 | return 1; /* we removed a handle */ | ||
115 | } | ||
116 | @@ -162,20 +160,15 @@ static void hashkey(struct connectdata *conn, char *buf, | ||
117 | msnprintf(buf, len, "%ld%s", port, hostname); | ||
118 | } | ||
119 | |||
120 | -void Curl_conncache_unlock(struct Curl_easy *data) | ||
121 | -{ | ||
122 | - CONN_UNLOCK(data); | ||
123 | -} | ||
124 | - | ||
125 | /* Returns number of connections currently held in the connection cache. | ||
126 | Locks/unlocks the cache itself! | ||
127 | */ | ||
128 | size_t Curl_conncache_size(struct Curl_easy *data) | ||
129 | { | ||
130 | size_t num; | ||
131 | - CONN_LOCK(data); | ||
132 | + CONNCACHE_LOCK(data); | ||
133 | num = data->state.conn_cache->num_conn; | ||
134 | - CONN_UNLOCK(data); | ||
135 | + CONNCACHE_UNLOCK(data); | ||
136 | return num; | ||
137 | } | ||
138 | |||
139 | @@ -188,7 +181,7 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, | ||
140 | const char **hostp) | ||
141 | { | ||
142 | struct connectbundle *bundle = NULL; | ||
143 | - CONN_LOCK(conn->data); | ||
144 | + CONNCACHE_LOCK(conn->data); | ||
145 | if(connc) { | ||
146 | char key[HASHKEY_SIZE]; | ||
147 | hashkey(conn, key, sizeof(key), hostp); | ||
148 | @@ -235,8 +228,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, | ||
149 | struct connectdata *conn) | ||
150 | { | ||
151 | CURLcode result = CURLE_OK; | ||
152 | - struct connectbundle *bundle; | ||
153 | - struct connectbundle *new_bundle = NULL; | ||
154 | + struct connectbundle *bundle = NULL; | ||
155 | struct Curl_easy *data = conn->data; | ||
156 | |||
157 | /* *find_bundle() locks the connection cache */ | ||
158 | @@ -245,20 +237,19 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, | ||
159 | int rc; | ||
160 | char key[HASHKEY_SIZE]; | ||
161 | |||
162 | - result = bundle_create(data, &new_bundle); | ||
163 | + result = bundle_create(&bundle); | ||
164 | if(result) { | ||
165 | goto unlock; | ||
166 | } | ||
167 | |||
168 | hashkey(conn, key, sizeof(key), NULL); | ||
169 | - rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle); | ||
170 | + rc = conncache_add_bundle(data->state.conn_cache, key, bundle); | ||
171 | |||
172 | if(!rc) { | ||
173 | - bundle_destroy(new_bundle); | ||
174 | + bundle_destroy(bundle); | ||
175 | result = CURLE_OUT_OF_MEMORY; | ||
176 | goto unlock; | ||
177 | } | ||
178 | - bundle = new_bundle; | ||
179 | } | ||
180 | |||
181 | bundle_add_conn(bundle, conn); | ||
182 | @@ -270,15 +261,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc, | ||
183 | conn->connection_id, connc->num_conn)); | ||
184 | |||
185 | unlock: | ||
186 | - CONN_UNLOCK(data); | ||
187 | + CONNCACHE_UNLOCK(data); | ||
188 | |||
189 | return result; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | - * Removes the connectdata object from the connection cache *and* clears the | ||
194 | - * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument | ||
195 | - * depending on if the parent function already holds the lock or not. | ||
196 | + * Removes the connectdata object from the connection cache, but does *not* | ||
197 | + * clear the conn->data association. The transfer still owns this connection. | ||
198 | + * | ||
199 | + * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function | ||
200 | + * already holds the lock or not. | ||
201 | */ | ||
202 | void Curl_conncache_remove_conn(struct Curl_easy *data, | ||
203 | struct connectdata *conn, bool lock) | ||
204 | @@ -290,7 +283,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, | ||
205 | due to a failed connection attempt, before being added to a bundle */ | ||
206 | if(bundle) { | ||
207 | if(lock) { | ||
208 | - CONN_LOCK(data); | ||
209 | + CONNCACHE_LOCK(data); | ||
210 | } | ||
211 | bundle_remove_conn(bundle, conn); | ||
212 | if(bundle->num_connections == 0) | ||
213 | @@ -301,9 +294,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data, | ||
214 | DEBUGF(infof(data, "The cache now contains %zu members\n", | ||
215 | connc->num_conn)); | ||
216 | } | ||
217 | - conn->data = NULL; /* clear the association */ | ||
218 | if(lock) { | ||
219 | - CONN_UNLOCK(data); | ||
220 | + CONNCACHE_UNLOCK(data); | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | @@ -332,7 +324,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data, | ||
225 | if(!connc) | ||
226 | return FALSE; | ||
227 | |||
228 | - CONN_LOCK(data); | ||
229 | + CONNCACHE_LOCK(data); | ||
230 | Curl_hash_start_iterate(&connc->hash, &iter); | ||
231 | |||
232 | he = Curl_hash_next_element(&iter); | ||
233 | @@ -350,12 +342,12 @@ bool Curl_conncache_foreach(struct Curl_easy *data, | ||
234 | curr = curr->next; | ||
235 | |||
236 | if(1 == func(conn, param)) { | ||
237 | - CONN_UNLOCK(data); | ||
238 | + CONNCACHE_UNLOCK(data); | ||
239 | return TRUE; | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | - CONN_UNLOCK(data); | ||
244 | + CONNCACHE_UNLOCK(data); | ||
245 | return FALSE; | ||
246 | } | ||
247 | |||
248 | @@ -494,7 +486,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) | ||
249 | |||
250 | now = Curl_now(); | ||
251 | |||
252 | - CONN_LOCK(data); | ||
253 | + CONNCACHE_LOCK(data); | ||
254 | Curl_hash_start_iterate(&connc->hash, &iter); | ||
255 | |||
256 | he = Curl_hash_next_element(&iter); | ||
257 | @@ -531,7 +523,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data) | ||
258 | connc->num_conn)); | ||
259 | conn_candidate->data = data; /* associate! */ | ||
260 | } | ||
261 | - CONN_UNLOCK(data); | ||
262 | + CONNCACHE_UNLOCK(data); | ||
263 | |||
264 | return conn_candidate; | ||
265 | } | ||
266 | @@ -548,6 +540,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc) | ||
267 | sigpipe_ignore(conn->data, &pipe_st); | ||
268 | /* This will remove the connection from the cache */ | ||
269 | connclose(conn, "kill all"); | ||
270 | + Curl_conncache_remove_conn(conn->data, conn, TRUE); | ||
271 | (void)Curl_disconnect(connc->closure_handle, conn, FALSE); | ||
272 | sigpipe_restore(&pipe_st); | ||
273 | |||
274 | diff --git a/lib/conncache.h b/lib/conncache.h | ||
275 | index e3e4c9c..3dda21c 100644 | ||
276 | --- a/lib/conncache.h | ||
277 | +++ b/lib/conncache.h | ||
278 | @@ -45,21 +45,21 @@ struct conncache { | ||
279 | #ifdef CURLDEBUG | ||
280 | /* the debug versions of these macros make extra certain that the lock is | ||
281 | never doubly locked or unlocked */ | ||
282 | -#define CONN_LOCK(x) if((x)->share) { \ | ||
283 | +#define CONNCACHE_LOCK(x) if((x)->share) { \ | ||
284 | Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \ | ||
285 | DEBUGASSERT(!(x)->state.conncache_lock); \ | ||
286 | (x)->state.conncache_lock = TRUE; \ | ||
287 | } | ||
288 | |||
289 | -#define CONN_UNLOCK(x) if((x)->share) { \ | ||
290 | +#define CONNCACHE_UNLOCK(x) if((x)->share) { \ | ||
291 | DEBUGASSERT((x)->state.conncache_lock); \ | ||
292 | (x)->state.conncache_lock = FALSE; \ | ||
293 | Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \ | ||
294 | } | ||
295 | #else | ||
296 | -#define CONN_LOCK(x) if((x)->share) \ | ||
297 | +#define CONNCACHE_LOCK(x) if((x)->share) \ | ||
298 | Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE) | ||
299 | -#define CONN_UNLOCK(x) if((x)->share) \ | ||
300 | +#define CONNCACHE_UNLOCK(x) if((x)->share) \ | ||
301 | Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT) | ||
302 | #endif | ||
303 | |||
304 | @@ -77,7 +77,6 @@ void Curl_conncache_destroy(struct conncache *connc); | ||
305 | struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, | ||
306 | struct conncache *connc, | ||
307 | const char **hostp); | ||
308 | -void Curl_conncache_unlock(struct Curl_easy *data); | ||
309 | /* returns number of connections currently held in the connection cache */ | ||
310 | size_t Curl_conncache_size(struct Curl_easy *data); | ||
311 | |||
312 | diff --git a/lib/hostip.c b/lib/hostip.c | ||
313 | index c0feb79..f5bb634 100644 | ||
314 | --- a/lib/hostip.c | ||
315 | +++ b/lib/hostip.c | ||
316 | @@ -1085,10 +1085,12 @@ CURLcode Curl_once_resolved(struct connectdata *conn, | ||
317 | |||
318 | result = Curl_setup_conn(conn, protocol_done); | ||
319 | |||
320 | - if(result) | ||
321 | - /* We're not allowed to return failure with memory left allocated | ||
322 | - in the connectdata struct, free those here */ | ||
323 | - Curl_disconnect(conn->data, conn, TRUE); /* close the connection */ | ||
324 | - | ||
325 | + if(result) { | ||
326 | + struct Curl_easy *data = conn->data; | ||
327 | + DEBUGASSERT(data); | ||
328 | + Curl_detach_connnection(data); | ||
329 | + Curl_conncache_remove_conn(data, conn, TRUE); | ||
330 | + Curl_disconnect(data, conn, TRUE); | ||
331 | + } | ||
332 | return result; | ||
333 | } | ||
334 | diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h | ||
335 | index 4f0ac16..a737f6f 100644 | ||
336 | --- a/lib/http_negotiate.h | ||
337 | +++ b/lib/http_negotiate.h | ||
338 | @@ -7,7 +7,7 @@ | ||
339 | * | (__| |_| | _ <| |___ | ||
340 | * \___|\___/|_| \_\_____| | ||
341 | * | ||
342 | - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
343 | + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
344 | * | ||
345 | * This software is licensed as described in the file COPYING, which | ||
346 | * you should have received as part of this distribution. The terms | ||
347 | @@ -33,6 +33,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); | ||
348 | |||
349 | void Curl_http_auth_cleanup_negotiate(struct connectdata *conn); | ||
350 | |||
351 | -#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ | ||
352 | +#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */ | ||
353 | +#define Curl_http_auth_cleanup_negotiate(x) | ||
354 | +#endif | ||
355 | |||
356 | #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ | ||
357 | diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h | ||
358 | index 003714d..3ebdf97 100644 | ||
359 | --- a/lib/http_ntlm.h | ||
360 | +++ b/lib/http_ntlm.h | ||
361 | @@ -7,7 +7,7 @@ | ||
362 | * | (__| |_| | _ <| |___ | ||
363 | * \___|\___/|_| \_\_____| | ||
364 | * | ||
365 | - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
366 | + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
367 | * | ||
368 | * This software is licensed as described in the file COPYING, which | ||
369 | * you should have received as part of this distribution. The terms | ||
370 | @@ -35,6 +35,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); | ||
371 | |||
372 | void Curl_http_auth_cleanup_ntlm(struct connectdata *conn); | ||
373 | |||
374 | -#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ | ||
375 | +#else /* !CURL_DISABLE_HTTP && USE_NTLM */ | ||
376 | +#define Curl_http_auth_cleanup_ntlm(x) | ||
377 | +#endif | ||
378 | |||
379 | #endif /* HEADER_CURL_HTTP_NTLM_H */ | ||
380 | diff --git a/lib/multi.c b/lib/multi.c | ||
381 | index e10e752..273653d 100644 | ||
382 | --- a/lib/multi.c | ||
383 | +++ b/lib/multi.c | ||
384 | @@ -79,7 +79,6 @@ static CURLMcode add_next_timeout(struct curltime now, | ||
385 | static CURLMcode multi_timeout(struct Curl_multi *multi, | ||
386 | long *timeout_ms); | ||
387 | static void process_pending_handles(struct Curl_multi *multi); | ||
388 | -static void detach_connnection(struct Curl_easy *data); | ||
389 | |||
390 | #ifdef DEBUGBUILD | ||
391 | static const char * const statename[]={ | ||
392 | @@ -112,7 +111,7 @@ static void Curl_init_completed(struct Curl_easy *data) | ||
393 | |||
394 | /* Important: reset the conn pointer so that we don't point to memory | ||
395 | that could be freed anytime */ | ||
396 | - detach_connnection(data); | ||
397 | + Curl_detach_connnection(data); | ||
398 | Curl_expire_clear(data); /* stop all timers */ | ||
399 | } | ||
400 | |||
401 | @@ -506,6 +505,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, | ||
402 | easy handle is added */ | ||
403 | memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall)); | ||
404 | |||
405 | + CONNCACHE_LOCK(data); | ||
406 | /* The closure handle only ever has default timeouts set. To improve the | ||
407 | state somewhat we clone the timeouts from each added handle so that the | ||
408 | closure handle always has the same timeouts as the most recently added | ||
409 | @@ -515,6 +515,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, | ||
410 | data->set.server_response_timeout; | ||
411 | data->state.conn_cache->closure_handle->set.no_signal = | ||
412 | data->set.no_signal; | ||
413 | + CONNCACHE_UNLOCK(data); | ||
414 | |||
415 | Curl_update_timer(multi); | ||
416 | return CURLM_OK; | ||
417 | @@ -589,14 +590,14 @@ static CURLcode multi_done(struct Curl_easy *data, | ||
418 | |||
419 | process_pending_handles(data->multi); /* connection / multiplex */ | ||
420 | |||
421 | - CONN_LOCK(data); | ||
422 | - detach_connnection(data); | ||
423 | + CONNCACHE_LOCK(data); | ||
424 | + Curl_detach_connnection(data); | ||
425 | if(CONN_INUSE(conn)) { | ||
426 | /* Stop if still used. */ | ||
427 | /* conn->data must not remain pointing to this transfer since it is going | ||
428 | away! Find another to own it! */ | ||
429 | conn->data = conn->easyq.head->ptr; | ||
430 | - CONN_UNLOCK(data); | ||
431 | + CONNCACHE_UNLOCK(data); | ||
432 | DEBUGF(infof(data, "Connection still in use %zu, " | ||
433 | "no more multi_done now!\n", | ||
434 | conn->easyq.size)); | ||
435 | @@ -647,7 +648,8 @@ static CURLcode multi_done(struct Curl_easy *data, | ||
436 | || (premature && !(conn->handler->flags & PROTOPT_STREAM))) { | ||
437 | CURLcode res2; | ||
438 | connclose(conn, "disconnecting"); | ||
439 | - CONN_UNLOCK(data); | ||
440 | + Curl_conncache_remove_conn(data, conn, FALSE); | ||
441 | + CONNCACHE_UNLOCK(data); | ||
442 | res2 = Curl_disconnect(data, conn, premature); | ||
443 | |||
444 | /* If we had an error already, make sure we return that one. But | ||
445 | @@ -666,7 +668,7 @@ static CURLcode multi_done(struct Curl_easy *data, | ||
446 | conn->bits.conn_to_host ? conn->conn_to_host.dispname : | ||
447 | conn->host.dispname); | ||
448 | /* the connection is no longer in use by this transfer */ | ||
449 | - CONN_UNLOCK(data); | ||
450 | + CONNCACHE_UNLOCK(data); | ||
451 | if(Curl_conncache_return_conn(data, conn)) { | ||
452 | /* remember the most recently used connection */ | ||
453 | data->state.lastconnect = conn; | ||
454 | @@ -774,8 +776,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, | ||
455 | vanish with this handle */ | ||
456 | |||
457 | /* Remove the association between the connection and the handle */ | ||
458 | - if(data->conn) | ||
459 | - detach_connnection(data); | ||
460 | + Curl_detach_connnection(data); | ||
461 | |||
462 | #ifdef USE_LIBPSL | ||
463 | /* Remove the PSL association. */ | ||
464 | @@ -824,9 +825,13 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi) | ||
465 | return (multi && (multi->multiplexing)); | ||
466 | } | ||
467 | |||
468 | -/* This is the only function that should clear data->conn. This will | ||
469 | - occasionally be called with the pointer already cleared. */ | ||
470 | -static void detach_connnection(struct Curl_easy *data) | ||
471 | +/* | ||
472 | + * Curl_detach_connnection() removes the given transfer from the connection. | ||
473 | + * | ||
474 | + * This is the only function that should clear data->conn. This will | ||
475 | + * occasionally be called with the data->conn pointer already cleared. | ||
476 | + */ | ||
477 | +void Curl_detach_connnection(struct Curl_easy *data) | ||
478 | { | ||
479 | struct connectdata *conn = data->conn; | ||
480 | if(conn) | ||
481 | @@ -834,7 +839,11 @@ static void detach_connnection(struct Curl_easy *data) | ||
482 | data->conn = NULL; | ||
483 | } | ||
484 | |||
485 | -/* This is the only function that should assign data->conn */ | ||
486 | +/* | ||
487 | + * Curl_attach_connnection() attaches this transfer to this connection. | ||
488 | + * | ||
489 | + * This is the only function that should assign data->conn | ||
490 | + */ | ||
491 | void Curl_attach_connnection(struct Curl_easy *data, | ||
492 | struct connectdata *conn) | ||
493 | { | ||
494 | @@ -1536,19 +1545,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | ||
495 | bool stream_error = FALSE; | ||
496 | rc = CURLM_OK; | ||
497 | |||
498 | - DEBUGASSERT((data->mstate <= CURLM_STATE_CONNECT) || | ||
499 | - (data->mstate >= CURLM_STATE_DONE) || | ||
500 | - data->conn); | ||
501 | - if(!data->conn && | ||
502 | - data->mstate > CURLM_STATE_CONNECT && | ||
503 | - data->mstate < CURLM_STATE_DONE) { | ||
504 | - /* In all these states, the code will blindly access 'data->conn' | ||
505 | - so this is precaution that it isn't NULL. And it silences static | ||
506 | - analyzers. */ | ||
507 | - failf(data, "In state %d with no conn, bail out!\n", data->mstate); | ||
508 | - return CURLM_INTERNAL_ERROR; | ||
509 | - } | ||
510 | - | ||
511 | if(multi_ischanged(multi, TRUE)) { | ||
512 | DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n")); | ||
513 | process_pending_handles(multi); /* multiplexed */ | ||
514 | @@ -2231,8 +2227,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | ||
515 | * access free'd data, if the connection is free'd and the handle | ||
516 | * removed before we perform the processing in CURLM_STATE_COMPLETED | ||
517 | */ | ||
518 | - if(data->conn) | ||
519 | - detach_connnection(data); | ||
520 | + Curl_detach_connnection(data); | ||
521 | } | ||
522 | |||
523 | #ifndef CURL_DISABLE_FTP | ||
524 | @@ -2284,7 +2279,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, | ||
525 | /* This is where we make sure that the conn pointer is reset. | ||
526 | We don't have to do this in every case block above where a | ||
527 | failure is detected */ | ||
528 | - detach_connnection(data); | ||
529 | + Curl_detach_connnection(data); | ||
530 | + | ||
531 | + /* remove connection from cache */ | ||
532 | + Curl_conncache_remove_conn(data, conn, TRUE); | ||
533 | |||
534 | /* disconnect properly */ | ||
535 | Curl_disconnect(data, conn, dead_connection); | ||
536 | diff --git a/lib/multiif.h b/lib/multiif.h | ||
537 | index bde755e..c07587b 100644 | ||
538 | --- a/lib/multiif.h | ||
539 | +++ b/lib/multiif.h | ||
540 | @@ -33,6 +33,7 @@ void Curl_expire_done(struct Curl_easy *data, expire_id id); | ||
541 | void Curl_update_timer(struct Curl_multi *multi); | ||
542 | void Curl_attach_connnection(struct Curl_easy *data, | ||
543 | struct connectdata *conn); | ||
544 | +void Curl_detach_connnection(struct Curl_easy *data); | ||
545 | bool Curl_multiplex_wanted(const struct Curl_multi *multi); | ||
546 | void Curl_set_in_callback(struct Curl_easy *data, bool value); | ||
547 | bool Curl_is_in_callback(struct Curl_easy *easy); | ||
548 | diff --git a/lib/url.c b/lib/url.c | ||
549 | index a826f8a..4ed0623 100644 | ||
550 | --- a/lib/url.c | ||
551 | +++ b/lib/url.c | ||
552 | @@ -679,9 +679,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn) | ||
553 | |||
554 | static void conn_shutdown(struct connectdata *conn) | ||
555 | { | ||
556 | - if(!conn) | ||
557 | - return; | ||
558 | - | ||
559 | + DEBUGASSERT(conn); | ||
560 | infof(conn->data, "Closing connection %ld\n", conn->connection_id); | ||
561 | DEBUGASSERT(conn->data); | ||
562 | |||
563 | @@ -702,16 +700,11 @@ static void conn_shutdown(struct connectdata *conn) | ||
564 | Curl_closesocket(conn, conn->tempsock[0]); | ||
565 | if(CURL_SOCKET_BAD != conn->tempsock[1]) | ||
566 | Curl_closesocket(conn, conn->tempsock[1]); | ||
567 | - | ||
568 | - /* unlink ourselves. this should be called last since other shutdown | ||
569 | - procedures need a valid conn->data and this may clear it. */ | ||
570 | - Curl_conncache_remove_conn(conn->data, conn, TRUE); | ||
571 | } | ||
572 | |||
573 | static void conn_free(struct connectdata *conn) | ||
574 | { | ||
575 | - if(!conn) | ||
576 | - return; | ||
577 | + DEBUGASSERT(conn); | ||
578 | |||
579 | Curl_free_idnconverted_hostname(&conn->host); | ||
580 | Curl_free_idnconverted_hostname(&conn->conn_to_host); | ||
581 | @@ -778,13 +771,17 @@ static void conn_free(struct connectdata *conn) | ||
582 | CURLcode Curl_disconnect(struct Curl_easy *data, | ||
583 | struct connectdata *conn, bool dead_connection) | ||
584 | { | ||
585 | - if(!conn) | ||
586 | - return CURLE_OK; /* this is closed and fine already */ | ||
587 | + /* there must be a connection to close */ | ||
588 | + DEBUGASSERT(conn); | ||
589 | |||
590 | - if(!data) { | ||
591 | - DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n")); | ||
592 | - return CURLE_OK; | ||
593 | - } | ||
594 | + /* it must be removed from the connection cache */ | ||
595 | + DEBUGASSERT(!conn->bundle); | ||
596 | + | ||
597 | + /* there must be an associated transfer */ | ||
598 | + DEBUGASSERT(data); | ||
599 | + | ||
600 | + /* the transfer must be detached from the connection */ | ||
601 | + DEBUGASSERT(!data->conn); | ||
602 | |||
603 | /* | ||
604 | * If this connection isn't marked to force-close, leave it open if there | ||
605 | @@ -800,16 +797,11 @@ CURLcode Curl_disconnect(struct Curl_easy *data, | ||
606 | conn->dns_entry = NULL; | ||
607 | } | ||
608 | |||
609 | - Curl_hostcache_prune(data); /* kill old DNS cache entries */ | ||
610 | - | ||
611 | -#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) | ||
612 | /* Cleanup NTLM connection-related data */ | ||
613 | Curl_http_auth_cleanup_ntlm(conn); | ||
614 | -#endif | ||
615 | -#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) | ||
616 | + | ||
617 | /* Cleanup NEGOTIATE connection-related data */ | ||
618 | Curl_http_auth_cleanup_negotiate(conn); | ||
619 | -#endif | ||
620 | |||
621 | /* the protocol specific disconnect handler and conn_shutdown need a transfer | ||
622 | for the connection! */ | ||
623 | @@ -1006,8 +998,12 @@ static int call_extract_if_dead(struct connectdata *conn, void *param) | ||
624 | static void prune_dead_connections(struct Curl_easy *data) | ||
625 | { | ||
626 | struct curltime now = Curl_now(); | ||
627 | - timediff_t elapsed = | ||
628 | + timediff_t elapsed; | ||
629 | + | ||
630 | + CONNCACHE_LOCK(data); | ||
631 | + elapsed = | ||
632 | Curl_timediff(now, data->state.conn_cache->last_cleanup); | ||
633 | + CONNCACHE_UNLOCK(data); | ||
634 | |||
635 | if(elapsed >= 1000L) { | ||
636 | struct prunedead prune; | ||
637 | @@ -1015,10 +1011,17 @@ static void prune_dead_connections(struct Curl_easy *data) | ||
638 | prune.extracted = NULL; | ||
639 | while(Curl_conncache_foreach(data, data->state.conn_cache, &prune, | ||
640 | call_extract_if_dead)) { | ||
641 | + /* unlocked */ | ||
642 | + | ||
643 | + /* remove connection from cache */ | ||
644 | + Curl_conncache_remove_conn(data, prune.extracted, TRUE); | ||
645 | + | ||
646 | /* disconnect it */ | ||
647 | (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE); | ||
648 | } | ||
649 | + CONNCACHE_LOCK(data); | ||
650 | data->state.conn_cache->last_cleanup = now; | ||
651 | + CONNCACHE_UNLOCK(data); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | @@ -1078,7 +1081,7 @@ ConnectionExists(struct Curl_easy *data, | ||
656 | if(data->set.pipewait) { | ||
657 | infof(data, "Server doesn't support multiplex yet, wait\n"); | ||
658 | *waitpipe = TRUE; | ||
659 | - Curl_conncache_unlock(data); | ||
660 | + CONNCACHE_UNLOCK(data); | ||
661 | return FALSE; /* no re-use */ | ||
662 | } | ||
663 | |||
664 | @@ -1402,11 +1405,12 @@ ConnectionExists(struct Curl_easy *data, | ||
665 | if(chosen) { | ||
666 | /* mark it as used before releasing the lock */ | ||
667 | chosen->data = data; /* own it! */ | ||
668 | - Curl_conncache_unlock(data); | ||
669 | + Curl_attach_connnection(data, chosen); | ||
670 | + CONNCACHE_UNLOCK(data); | ||
671 | *usethis = chosen; | ||
672 | return TRUE; /* yes, we found one to use! */ | ||
673 | } | ||
674 | - Curl_conncache_unlock(data); | ||
675 | + CONNCACHE_UNLOCK(data); | ||
676 | |||
677 | if(foundPendingCandidate && data->set.pipewait) { | ||
678 | infof(data, | ||
679 | @@ -3519,6 +3523,7 @@ static CURLcode create_conn(struct Curl_easy *data, | ||
680 | if(!result) { | ||
681 | conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */ | ||
682 | |||
683 | + Curl_attach_connnection(data, conn); | ||
684 | result = Curl_conncache_add_conn(data->state.conn_cache, conn); | ||
685 | if(result) | ||
686 | goto out; | ||
687 | @@ -3533,7 +3538,6 @@ static CURLcode create_conn(struct Curl_easy *data, | ||
688 | (void)conn->handler->done(conn, result, FALSE); | ||
689 | goto out; | ||
690 | } | ||
691 | - Curl_attach_connnection(data, conn); | ||
692 | Curl_setup_transfer(data, -1, -1, FALSE, -1); | ||
693 | } | ||
694 | |||
695 | @@ -3683,7 +3687,7 @@ static CURLcode create_conn(struct Curl_easy *data, | ||
696 | |||
697 | /* The bundle is full. Extract the oldest connection. */ | ||
698 | conn_candidate = Curl_conncache_extract_bundle(data, bundle); | ||
699 | - Curl_conncache_unlock(data); | ||
700 | + CONNCACHE_UNLOCK(data); | ||
701 | |||
702 | if(conn_candidate) | ||
703 | (void)Curl_disconnect(data, conn_candidate, | ||
704 | @@ -3695,7 +3699,7 @@ static CURLcode create_conn(struct Curl_easy *data, | ||
705 | } | ||
706 | } | ||
707 | else | ||
708 | - Curl_conncache_unlock(data); | ||
709 | + CONNCACHE_UNLOCK(data); | ||
710 | |||
711 | } | ||
712 | |||
713 | @@ -3729,6 +3733,8 @@ static CURLcode create_conn(struct Curl_easy *data, | ||
714 | * This is a brand new connection, so let's store it in the connection | ||
715 | * cache of ours! | ||
716 | */ | ||
717 | + Curl_attach_connnection(data, conn); | ||
718 | + | ||
719 | result = Curl_conncache_add_conn(data->state.conn_cache, conn); | ||
720 | if(result) | ||
721 | goto out; | ||
722 | @@ -3883,7 +3889,7 @@ CURLcode Curl_connect(struct Curl_easy *data, | ||
723 | result = create_conn(data, &conn, asyncp); | ||
724 | |||
725 | if(!result) { | ||
726 | - if(CONN_INUSE(conn)) | ||
727 | + if(CONN_INUSE(conn) > 1) | ||
728 | /* multiplexed */ | ||
729 | *protocol_done = TRUE; | ||
730 | else if(!*asyncp) { | ||
731 | @@ -3900,11 +3906,10 @@ CURLcode Curl_connect(struct Curl_easy *data, | ||
732 | else if(result && conn) { | ||
733 | /* We're not allowed to return failure with memory left allocated in the | ||
734 | connectdata struct, free those here */ | ||
735 | + Curl_detach_connnection(data); | ||
736 | + Curl_conncache_remove_conn(data, conn, TRUE); | ||
737 | Curl_disconnect(data, conn, TRUE); | ||
738 | } | ||
739 | - else if(!result && !data->conn) | ||
740 | - /* FILE: transfers already have the connection attached */ | ||
741 | - Curl_attach_connnection(data, conn); | ||
742 | |||
743 | return result; | ||
744 | } | ||
745 | diff --git a/tests/data/test1554 b/tests/data/test1554 | ||
746 | index 06f1897..d3926d9 100644 | ||
747 | --- a/tests/data/test1554 | ||
748 | +++ b/tests/data/test1554 | ||
749 | @@ -29,6 +29,12 @@ run 1: foobar and so on fun! | ||
750 | <- Mutex unlock | ||
751 | -> Mutex lock | ||
752 | <- Mutex unlock | ||
753 | +-> Mutex lock | ||
754 | +<- Mutex unlock | ||
755 | +-> Mutex lock | ||
756 | +<- Mutex unlock | ||
757 | +-> Mutex lock | ||
758 | +<- Mutex unlock | ||
759 | run 1: foobar and so on fun! | ||
760 | -> Mutex lock | ||
761 | <- Mutex unlock | ||
762 | @@ -40,6 +46,10 @@ run 1: foobar and so on fun! | ||
763 | <- Mutex unlock | ||
764 | -> Mutex lock | ||
765 | <- Mutex unlock | ||
766 | +-> Mutex lock | ||
767 | +<- Mutex unlock | ||
768 | +-> Mutex lock | ||
769 | +<- Mutex unlock | ||
770 | run 1: foobar and so on fun! | ||
771 | -> Mutex lock | ||
772 | <- Mutex unlock | ||
773 | @@ -51,6 +61,10 @@ run 1: foobar and so on fun! | ||
774 | <- Mutex unlock | ||
775 | -> Mutex lock | ||
776 | <- Mutex unlock | ||
777 | +-> Mutex lock | ||
778 | +<- Mutex unlock | ||
779 | +-> Mutex lock | ||
780 | +<- Mutex unlock | ||
781 | run 1: foobar and so on fun! | ||
782 | -> Mutex lock | ||
783 | <- Mutex unlock | ||
784 | diff --git a/tests/unit/unit1620.c b/tests/unit/unit1620.c | ||
785 | index 6e572c6..b23e5b9 100644 | ||
786 | --- a/tests/unit/unit1620.c | ||
787 | +++ b/tests/unit/unit1620.c | ||
788 | @@ -5,7 +5,7 @@ | ||
789 | * | (__| |_| | _ <| |___ | ||
790 | * \___|\___/|_| \_\_____| | ||
791 | * | ||
792 | - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
793 | + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
794 | * | ||
795 | * This software is licensed as described in the file COPYING, which | ||
796 | * you should have received as part of this distribution. The terms | ||
797 | @@ -73,10 +73,6 @@ UNITTEST_START | ||
798 | fail_unless(rc == CURLE_OK, | ||
799 | "Curl_parse_login_details() failed"); | ||
800 | |||
801 | - rc = Curl_disconnect(empty, empty->conn, FALSE); | ||
802 | - fail_unless(rc == CURLE_OK, | ||
803 | - "Curl_disconnect() with dead_connection set FALSE failed"); | ||
804 | - | ||
805 | Curl_freeset(empty); | ||
806 | for(i = (enum dupstring)0; i < STRING_LAST; i++) { | ||
807 | fail_unless(empty->set.str[i] == NULL, | ||
808 | -- | ||
809 | 2.25.4 | ||
810 | |||
811 | |||
812 | From 6830828c9eecd9ab14404f2f49f19b56dec62130 Mon Sep 17 00:00:00 2001 | ||
813 | From: Marc Aldorasi <marc@groundctl.com> | ||
814 | Date: Thu, 30 Jul 2020 14:16:17 -0400 | ||
815 | Subject: [PATCH 2/3] multi_remove_handle: close unused connect-only | ||
816 | connections | ||
817 | |||
818 | Previously any connect-only connections in a multi handle would be kept | ||
819 | alive until the multi handle was closed. Since these connections cannot | ||
820 | be re-used, they can be marked for closure when the associated easy | ||
821 | handle is removed from the multi handle. | ||
822 | |||
823 | Closes #5749 | ||
824 | |||
825 | Upstream-commit: d5bb459ccf1fc5980ae4b95c05b4ecf6454a7599 | ||
826 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
827 | --- | ||
828 | lib/multi.c | 34 ++++++++++++++++++++++++++++++---- | ||
829 | tests/data/test1554 | 6 ++++++ | ||
830 | 2 files changed, 36 insertions(+), 4 deletions(-) | ||
831 | |||
832 | diff --git a/lib/multi.c b/lib/multi.c | ||
833 | index 249e360..f1371bd 100644 | ||
834 | --- a/lib/multi.c | ||
835 | +++ b/lib/multi.c | ||
836 | @@ -682,6 +682,26 @@ static CURLcode multi_done(struct Curl_easy *data, | ||
837 | return result; | ||
838 | } | ||
839 | |||
840 | +static int close_connect_only(struct connectdata *conn, void *param) | ||
841 | +{ | ||
842 | + struct Curl_easy *data = param; | ||
843 | + | ||
844 | + if(data->state.lastconnect != conn) | ||
845 | + return 0; | ||
846 | + | ||
847 | + if(conn->data != data) | ||
848 | + return 1; | ||
849 | + conn->data = NULL; | ||
850 | + | ||
851 | + if(!conn->bits.connect_only) | ||
852 | + return 1; | ||
853 | + | ||
854 | + connclose(conn, "Removing connect-only easy handle"); | ||
855 | + conn->bits.connect_only = FALSE; | ||
856 | + | ||
857 | + return 1; | ||
858 | +} | ||
859 | + | ||
860 | CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, | ||
861 | struct Curl_easy *data) | ||
862 | { | ||
863 | @@ -765,10 +785,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, | ||
864 | multi_done() as that may actually call Curl_expire that uses this */ | ||
865 | Curl_llist_destroy(&data->state.timeoutlist, NULL); | ||
866 | |||
867 | - /* as this was using a shared connection cache we clear the pointer to that | ||
868 | - since we're not part of that multi handle anymore */ | ||
869 | - data->state.conn_cache = NULL; | ||
870 | - | ||
871 | /* change state without using multistate(), only to make singlesocket() do | ||
872 | what we want */ | ||
873 | data->mstate = CURLM_STATE_COMPLETED; | ||
874 | @@ -778,12 +794,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, | ||
875 | /* Remove the association between the connection and the handle */ | ||
876 | Curl_detach_connnection(data); | ||
877 | |||
878 | + if(data->state.lastconnect) { | ||
879 | + /* Mark any connect-only connection for closure */ | ||
880 | + Curl_conncache_foreach(data, data->state.conn_cache, | ||
881 | + data, &close_connect_only); | ||
882 | + } | ||
883 | + | ||
884 | #ifdef USE_LIBPSL | ||
885 | /* Remove the PSL association. */ | ||
886 | if(data->psl == &multi->psl) | ||
887 | data->psl = NULL; | ||
888 | #endif | ||
889 | |||
890 | + /* as this was using a shared connection cache we clear the pointer to that | ||
891 | + since we're not part of that multi handle anymore */ | ||
892 | + data->state.conn_cache = NULL; | ||
893 | + | ||
894 | data->multi = NULL; /* clear the association to this multi handle */ | ||
895 | |||
896 | /* make sure there's no pending message in the queue sent from this easy | ||
897 | diff --git a/tests/data/test1554 b/tests/data/test1554 | ||
898 | index d3926d9..fffa6ad 100644 | ||
899 | --- a/tests/data/test1554 | ||
900 | +++ b/tests/data/test1554 | ||
901 | @@ -50,6 +50,8 @@ run 1: foobar and so on fun! | ||
902 | <- Mutex unlock | ||
903 | -> Mutex lock | ||
904 | <- Mutex unlock | ||
905 | +-> Mutex lock | ||
906 | +<- Mutex unlock | ||
907 | run 1: foobar and so on fun! | ||
908 | -> Mutex lock | ||
909 | <- Mutex unlock | ||
910 | @@ -65,6 +67,8 @@ run 1: foobar and so on fun! | ||
911 | <- Mutex unlock | ||
912 | -> Mutex lock | ||
913 | <- Mutex unlock | ||
914 | +-> Mutex lock | ||
915 | +<- Mutex unlock | ||
916 | run 1: foobar and so on fun! | ||
917 | -> Mutex lock | ||
918 | <- Mutex unlock | ||
919 | @@ -74,6 +78,8 @@ run 1: foobar and so on fun! | ||
920 | <- Mutex unlock | ||
921 | -> Mutex lock | ||
922 | <- Mutex unlock | ||
923 | +-> Mutex lock | ||
924 | +<- Mutex unlock | ||
925 | </datacheck> | ||
926 | </reply> | ||
927 | |||
928 | -- | ||
929 | 2.25.4 | ||
930 | |||
931 | |||
932 | From 01148ee40dd913a169435b0f9ea90e6393821e70 Mon Sep 17 00:00:00 2001 | ||
933 | From: Daniel Stenberg <daniel@haxx.se> | ||
934 | Date: Sun, 16 Aug 2020 11:34:35 +0200 | ||
935 | Subject: [PATCH 3/3] Curl_easy: remember last connection by id, not by pointer | ||
936 | |||
937 | CVE-2020-8231 | ||
938 | |||
939 | Bug: https://curl.haxx.se/docs/CVE-2020-8231.html | ||
940 | |||
941 | Reported-by: Marc Aldorasi | ||
942 | Closes #5824 | ||
943 | |||
944 | Upstream-commit: 3c9e021f86872baae412a427e807fbfa2f3e8a22 | ||
945 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
946 | --- | ||
947 | lib/connect.c | 19 ++++++++++--------- | ||
948 | lib/easy.c | 3 +-- | ||
949 | lib/multi.c | 9 +++++---- | ||
950 | lib/url.c | 2 +- | ||
951 | lib/urldata.h | 2 +- | ||
952 | 5 files changed, 18 insertions(+), 17 deletions(-) | ||
953 | |||
954 | diff --git a/lib/connect.c b/lib/connect.c | ||
955 | index 29293f0..e1c5662 100644 | ||
956 | --- a/lib/connect.c | ||
957 | +++ b/lib/connect.c | ||
958 | @@ -1356,15 +1356,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ | ||
959 | } | ||
960 | |||
961 | struct connfind { | ||
962 | - struct connectdata *tofind; | ||
963 | - bool found; | ||
964 | + long id_tofind; | ||
965 | + struct connectdata *found; | ||
966 | }; | ||
967 | |||
968 | static int conn_is_conn(struct connectdata *conn, void *param) | ||
969 | { | ||
970 | struct connfind *f = (struct connfind *)param; | ||
971 | - if(conn == f->tofind) { | ||
972 | - f->found = TRUE; | ||
973 | + if(conn->connection_id == f->id_tofind) { | ||
974 | + f->found = conn; | ||
975 | return 1; | ||
976 | } | ||
977 | return 0; | ||
978 | @@ -1386,21 +1386,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, | ||
979 | * - that is associated with a multi handle, and whose connection | ||
980 | * was detached with CURLOPT_CONNECT_ONLY | ||
981 | */ | ||
982 | - if(data->state.lastconnect && (data->multi_easy || data->multi)) { | ||
983 | - struct connectdata *c = data->state.lastconnect; | ||
984 | + if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) { | ||
985 | + struct connectdata *c; | ||
986 | struct connfind find; | ||
987 | - find.tofind = data->state.lastconnect; | ||
988 | - find.found = FALSE; | ||
989 | + find.id_tofind = data->state.lastconnect_id; | ||
990 | + find.found = NULL; | ||
991 | |||
992 | Curl_conncache_foreach(data, data->multi_easy? | ||
993 | &data->multi_easy->conn_cache: | ||
994 | &data->multi->conn_cache, &find, conn_is_conn); | ||
995 | |||
996 | if(!find.found) { | ||
997 | - data->state.lastconnect = NULL; | ||
998 | + data->state.lastconnect_id = -1; | ||
999 | return CURL_SOCKET_BAD; | ||
1000 | } | ||
1001 | |||
1002 | + c = find.found; | ||
1003 | if(connp) { | ||
1004 | /* only store this if the caller cares for it */ | ||
1005 | *connp = c; | ||
1006 | diff --git a/lib/easy.c b/lib/easy.c | ||
1007 | index 292cca7..a69eb9e 100644 | ||
1008 | --- a/lib/easy.c | ||
1009 | +++ b/lib/easy.c | ||
1010 | @@ -831,8 +831,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) | ||
1011 | |||
1012 | /* the connection cache is setup on demand */ | ||
1013 | outcurl->state.conn_cache = NULL; | ||
1014 | - | ||
1015 | - outcurl->state.lastconnect = NULL; | ||
1016 | + outcurl->state.lastconnect_id = -1; | ||
1017 | |||
1018 | outcurl->progress.flags = data->progress.flags; | ||
1019 | outcurl->progress.callback = data->progress.callback; | ||
1020 | diff --git a/lib/multi.c b/lib/multi.c | ||
1021 | index f1371bd..778c537 100644 | ||
1022 | --- a/lib/multi.c | ||
1023 | +++ b/lib/multi.c | ||
1024 | @@ -453,6 +453,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, | ||
1025 | data->state.conn_cache = &data->share->conn_cache; | ||
1026 | else | ||
1027 | data->state.conn_cache = &multi->conn_cache; | ||
1028 | + data->state.lastconnect_id = -1; | ||
1029 | |||
1030 | #ifdef USE_LIBPSL | ||
1031 | /* Do the same for PSL. */ | ||
1032 | @@ -671,11 +672,11 @@ static CURLcode multi_done(struct Curl_easy *data, | ||
1033 | CONNCACHE_UNLOCK(data); | ||
1034 | if(Curl_conncache_return_conn(data, conn)) { | ||
1035 | /* remember the most recently used connection */ | ||
1036 | - data->state.lastconnect = conn; | ||
1037 | + data->state.lastconnect_id = conn->connection_id; | ||
1038 | infof(data, "%s\n", buffer); | ||
1039 | } | ||
1040 | else | ||
1041 | - data->state.lastconnect = NULL; | ||
1042 | + data->state.lastconnect_id = -1; | ||
1043 | } | ||
1044 | |||
1045 | Curl_free_request_state(data); | ||
1046 | @@ -686,7 +687,7 @@ static int close_connect_only(struct connectdata *conn, void *param) | ||
1047 | { | ||
1048 | struct Curl_easy *data = param; | ||
1049 | |||
1050 | - if(data->state.lastconnect != conn) | ||
1051 | + if(data->state.lastconnect_id != conn->connection_id) | ||
1052 | return 0; | ||
1053 | |||
1054 | if(conn->data != data) | ||
1055 | @@ -794,7 +795,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, | ||
1056 | /* Remove the association between the connection and the handle */ | ||
1057 | Curl_detach_connnection(data); | ||
1058 | |||
1059 | - if(data->state.lastconnect) { | ||
1060 | + if(data->state.lastconnect_id != -1) { | ||
1061 | /* Mark any connect-only connection for closure */ | ||
1062 | Curl_conncache_foreach(data, data->state.conn_cache, | ||
1063 | data, &close_connect_only); | ||
1064 | diff --git a/lib/url.c b/lib/url.c | ||
1065 | index a1a6b69..2919a3d 100644 | ||
1066 | --- a/lib/url.c | ||
1067 | +++ b/lib/url.c | ||
1068 | @@ -617,7 +617,7 @@ CURLcode Curl_open(struct Curl_easy **curl) | ||
1069 | Curl_initinfo(data); | ||
1070 | |||
1071 | /* most recent connection is not yet defined */ | ||
1072 | - data->state.lastconnect = NULL; | ||
1073 | + data->state.lastconnect_id = -1; | ||
1074 | |||
1075 | data->progress.flags |= PGRS_HIDE; | ||
1076 | data->state.current_speed = -1; /* init to negative == impossible */ | ||
1077 | diff --git a/lib/urldata.h b/lib/urldata.h | ||
1078 | index f80a02d..6d8eb69 100644 | ||
1079 | --- a/lib/urldata.h | ||
1080 | +++ b/lib/urldata.h | ||
1081 | @@ -1332,7 +1332,7 @@ struct UrlState { | ||
1082 | /* buffers to store authentication data in, as parsed from input options */ | ||
1083 | struct curltime keeps_speed; /* for the progress meter really */ | ||
1084 | |||
1085 | - struct connectdata *lastconnect; /* The last connection, NULL if undefined */ | ||
1086 | + long lastconnect_id; /* The last connection, -1 if undefined */ | ||
1087 | |||
1088 | char *headerbuff; /* allocated buffer to store headers in */ | ||
1089 | size_t headersize; /* size of the allocation */ | ||
1090 | -- | ||
1091 | 2.25.4 | ||
1092 | |||
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8284.patch b/meta/recipes-support/curl/curl/CVE-2020-8284.patch new file mode 100644 index 0000000000..ed6e8049a6 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2020-8284.patch | |||
@@ -0,0 +1,209 @@ | |||
1 | From ec9cc725d598ac77de7b6df8afeec292b3c8ad46 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Tue, 24 Nov 2020 14:56:57 +0100 | ||
4 | Subject: [PATCH] ftp: CURLOPT_FTP_SKIP_PASV_IP by default | ||
5 | |||
6 | The command line tool also independently sets --ftp-skip-pasv-ip by | ||
7 | default. | ||
8 | |||
9 | Ten test cases updated to adapt the modified --libcurl output. | ||
10 | |||
11 | Bug: https://curl.se/docs/CVE-2020-8284.html | ||
12 | CVE-2020-8284 | ||
13 | |||
14 | Reported-by: Varnavas Papaioannou | ||
15 | |||
16 | Upstream-Status: Backport [https://github.com/curl/curl/commit/ec9cc725d598ac] | ||
17 | CVE: CVE-2020-8284 | ||
18 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
19 | |||
20 | --- | ||
21 | docs/cmdline-opts/ftp-skip-pasv-ip.d | 2 ++ | ||
22 | docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | 8 +++++--- | ||
23 | lib/url.c | 1 + | ||
24 | src/tool_cfgable.c | 1 + | ||
25 | tests/data/test1400 | 1 + | ||
26 | tests/data/test1401 | 1 + | ||
27 | tests/data/test1402 | 1 + | ||
28 | tests/data/test1403 | 1 + | ||
29 | tests/data/test1404 | 1 + | ||
30 | tests/data/test1405 | 1 + | ||
31 | tests/data/test1406 | 1 + | ||
32 | tests/data/test1407 | 1 + | ||
33 | tests/data/test1420 | 1 + | ||
34 | 14 files changed, 18 insertions(+), 3 deletions(-) | ||
35 | |||
36 | diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d | ||
37 | index d6fd4589b1e..bcf4e7e62f2 100644 | ||
38 | --- a/docs/cmdline-opts/ftp-skip-pasv-ip.d | ||
39 | +++ b/docs/cmdline-opts/ftp-skip-pasv-ip.d | ||
40 | @@ -10,4 +10,6 @@ to curl's PASV command when curl connects the data connection. Instead curl | ||
41 | will re-use the same IP address it already uses for the control | ||
42 | connection. | ||
43 | |||
44 | +Since curl 7.74.0 this option is enabled by default. | ||
45 | + | ||
46 | This option has no effect if PORT, EPRT or EPSV is used instead of PASV. | ||
47 | diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | ||
48 | index d6217d0d8ca..fa87ddce769 100644 | ||
49 | --- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | ||
50 | +++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 | ||
51 | @@ -5,7 +5,7 @@ | ||
52 | .\" * | (__| |_| | _ <| |___ | ||
53 | .\" * \___|\___/|_| \_\_____| | ||
54 | .\" * | ||
55 | -.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
56 | +.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. | ||
57 | .\" * | ||
58 | .\" * This software is licensed as described in the file COPYING, which | ||
59 | .\" * you should have received as part of this distribution. The terms | ||
60 | @@ -35,11 +35,13 @@ address it already uses for the control connection. But it will use the port | ||
61 | number from the 227-response. | ||
62 | |||
63 | This option thus allows libcurl to work around broken server installations | ||
64 | -that due to NATs, firewalls or incompetence report the wrong IP address back. | ||
65 | +that due to NATs, firewalls or incompetence report the wrong IP address | ||
66 | +back. Setting the option also reduces the risk for various sorts of client | ||
67 | +abuse by malicious servers. | ||
68 | |||
69 | This option has no effect if PORT, EPRT or EPSV is used instead of PASV. | ||
70 | .SH DEFAULT | ||
71 | -0 | ||
72 | +1 since 7.74.0, was 0 before then. | ||
73 | .SH PROTOCOLS | ||
74 | FTP | ||
75 | .SH EXAMPLE | ||
76 | diff --git a/lib/url.c b/lib/url.c | ||
77 | index f8b2a0030de..2b0ba87ba87 100644 | ||
78 | --- a/lib/url.c | ||
79 | +++ b/lib/url.c | ||
80 | @@ -497,6 +497,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) | ||
81 | set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */ | ||
82 | set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */ | ||
83 | set->ftp_filemethod = FTPFILE_MULTICWD; | ||
84 | + set->ftp_skip_ip = TRUE; /* skip PASV IP by default */ | ||
85 | #endif | ||
86 | set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ | ||
87 | |||
88 | diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c | ||
89 | index c52d8e1c6bb..4c06d3557b7 100644 | ||
90 | --- a/src/tool_cfgable.c | ||
91 | +++ b/src/tool_cfgable.c | ||
92 | @@ -44,6 +44,7 @@ void config_init(struct OperationConfig *config) | ||
93 | config->tcp_nodelay = TRUE; /* enabled by default */ | ||
94 | config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT; | ||
95 | config->http09_allowed = FALSE; | ||
96 | + config->ftp_skip_ip = TRUE; | ||
97 | } | ||
98 | |||
99 | static void free_config_fields(struct OperationConfig *config) | ||
100 | diff --git a/tests/data/test1400 b/tests/data/test1400 | ||
101 | index 812ad0b88d9..b7060eca58e 100644 | ||
102 | --- a/tests/data/test1400 | ||
103 | +++ b/tests/data/test1400 | ||
104 | @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) | ||
105 | curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); | ||
106 | curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
107 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
108 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
109 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
110 | |||
111 | /* Here is a list of options the curl code used that cannot get generated | ||
112 | diff --git a/tests/data/test1401 b/tests/data/test1401 | ||
113 | index f93b3d637de..a2629683aff 100644 | ||
114 | --- a/tests/data/test1401 | ||
115 | +++ b/tests/data/test1401 | ||
116 | @@ -87,6 +87,7 @@ int main(int argc, char *argv[]) | ||
117 | curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
118 | curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip"); | ||
119 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
120 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
121 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
122 | curl_easy_setopt(hnd, CURLOPT_PROTOCOLS, (long)CURLPROTO_FILE | | ||
123 | (long)CURLPROTO_FTP | | ||
124 | diff --git a/tests/data/test1402 b/tests/data/test1402 | ||
125 | index 7593c516da1..1bd55cb4e3b 100644 | ||
126 | --- a/tests/data/test1402 | ||
127 | +++ b/tests/data/test1402 | ||
128 | @@ -78,6 +78,7 @@ int main(int argc, char *argv[]) | ||
129 | curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); | ||
130 | curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
131 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
132 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
133 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
134 | |||
135 | /* Here is a list of options the curl code used that cannot get generated | ||
136 | diff --git a/tests/data/test1403 b/tests/data/test1403 | ||
137 | index ecb4dd3dcab..a7c9fcca322 100644 | ||
138 | --- a/tests/data/test1403 | ||
139 | +++ b/tests/data/test1403 | ||
140 | @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) | ||
141 | curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); | ||
142 | curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
143 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
144 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
145 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
146 | |||
147 | /* Here is a list of options the curl code used that cannot get generated | ||
148 | diff --git a/tests/data/test1404 b/tests/data/test1404 | ||
149 | index 97622b63948..1d8e8cf7779 100644 | ||
150 | --- a/tests/data/test1404 | ||
151 | +++ b/tests/data/test1404 | ||
152 | @@ -147,6 +147,7 @@ int main(int argc, char *argv[]) | ||
153 | curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped"); | ||
154 | curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); | ||
155 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
156 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
157 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
158 | |||
159 | /* Here is a list of options the curl code used that cannot get generated | ||
160 | diff --git a/tests/data/test1405 b/tests/data/test1405 | ||
161 | index 2bac79eda74..b4087704f7b 100644 | ||
162 | --- a/tests/data/test1405 | ||
163 | +++ b/tests/data/test1405 | ||
164 | @@ -89,6 +89,7 @@ int main(int argc, char *argv[]) | ||
165 | curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, slist2); | ||
166 | curl_easy_setopt(hnd, CURLOPT_PREQUOTE, slist3); | ||
167 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
168 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
169 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
170 | |||
171 | /* Here is a list of options the curl code used that cannot get generated | ||
172 | diff --git a/tests/data/test1406 b/tests/data/test1406 | ||
173 | index 51a166adff2..38f68d11ee1 100644 | ||
174 | --- a/tests/data/test1406 | ||
175 | +++ b/tests/data/test1406 | ||
176 | @@ -79,6 +79,7 @@ int main(int argc, char *argv[]) | ||
177 | curl_easy_setopt(hnd, CURLOPT_URL, "smtp://%HOSTIP:%SMTPPORT/1406"); | ||
178 | curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); | ||
179 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
180 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
181 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
182 | curl_easy_setopt(hnd, CURLOPT_MAIL_FROM, "sender@example.com"); | ||
183 | curl_easy_setopt(hnd, CURLOPT_MAIL_RCPT, slist1); | ||
184 | diff --git a/tests/data/test1407 b/tests/data/test1407 | ||
185 | index f6879008fb2..a7e13ba7585 100644 | ||
186 | --- a/tests/data/test1407 | ||
187 | +++ b/tests/data/test1407 | ||
188 | @@ -62,6 +62,7 @@ int main(int argc, char *argv[]) | ||
189 | curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 1L); | ||
190 | curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); | ||
191 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
192 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
193 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
194 | |||
195 | /* Here is a list of options the curl code used that cannot get generated | ||
196 | diff --git a/tests/data/test1420 b/tests/data/test1420 | ||
197 | index 057ecc4773a..4b8d7bbf418 100644 | ||
198 | --- a/tests/data/test1420 | ||
199 | +++ b/tests/data/test1420 | ||
200 | @@ -67,6 +67,7 @@ int main(int argc, char *argv[]) | ||
201 | curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;MAILINDEX=1"); | ||
202 | curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret"); | ||
203 | curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); | ||
204 | + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); | ||
205 | curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); | ||
206 | |||
207 | /* Here is a list of options the curl code used that cannot get generated | ||
208 | |||
209 | |||
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8285.patch b/meta/recipes-support/curl/curl/CVE-2020-8285.patch new file mode 100644 index 0000000000..a66729b180 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2020-8285.patch | |||
@@ -0,0 +1,260 @@ | |||
1 | From 6fda045b19a9066701b5e09cfa657a13a3accbf3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Sat, 28 Nov 2020 00:27:21 +0100 | ||
4 | Subject: [PATCH] ftp: make wc_statemach loop instead of recurse | ||
5 | |||
6 | CVE-2020-8285 | ||
7 | |||
8 | Fixes #6255 | ||
9 | Bug: https://curl.se/docs/CVE-2020-8285.html | ||
10 | Reported-by: xnynx on github | ||
11 | |||
12 | Upstream-commit: 69a358f2186e04cf44698b5100332cbf1ee7f01d | ||
13 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
14 | |||
15 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0006-curl-7.69.1-CVE-2020-8285.patch] | ||
16 | CVE: CVE-2020-8285 | ||
17 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
18 | --- | ||
19 | lib/ftp.c | 202 +++++++++++++++++++++++++++--------------------------- | ||
20 | 1 file changed, 102 insertions(+), 100 deletions(-) | ||
21 | |||
22 | diff --git a/lib/ftp.c b/lib/ftp.c | ||
23 | index 57b22ad..3382772 100644 | ||
24 | --- a/lib/ftp.c | ||
25 | +++ b/lib/ftp.c | ||
26 | @@ -3763,129 +3763,131 @@ static CURLcode init_wc_data(struct connectdata *conn) | ||
27 | return result; | ||
28 | } | ||
29 | |||
30 | -/* This is called recursively */ | ||
31 | static CURLcode wc_statemach(struct connectdata *conn) | ||
32 | { | ||
33 | struct WildcardData * const wildcard = &(conn->data->wildcard); | ||
34 | CURLcode result = CURLE_OK; | ||
35 | |||
36 | - switch(wildcard->state) { | ||
37 | - case CURLWC_INIT: | ||
38 | - result = init_wc_data(conn); | ||
39 | - if(wildcard->state == CURLWC_CLEAN) | ||
40 | - /* only listing! */ | ||
41 | - break; | ||
42 | - wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; | ||
43 | - break; | ||
44 | + for(;;) { | ||
45 | + switch(wildcard->state) { | ||
46 | + case CURLWC_INIT: | ||
47 | + result = init_wc_data(conn); | ||
48 | + if(wildcard->state == CURLWC_CLEAN) | ||
49 | + /* only listing! */ | ||
50 | + return result; | ||
51 | + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; | ||
52 | + return result; | ||
53 | |||
54 | - case CURLWC_MATCHING: { | ||
55 | - /* In this state is LIST response successfully parsed, so lets restore | ||
56 | - previous WRITEFUNCTION callback and WRITEDATA pointer */ | ||
57 | - struct ftp_wc *ftpwc = wildcard->protdata; | ||
58 | - conn->data->set.fwrite_func = ftpwc->backup.write_function; | ||
59 | - conn->data->set.out = ftpwc->backup.file_descriptor; | ||
60 | - ftpwc->backup.write_function = ZERO_NULL; | ||
61 | - ftpwc->backup.file_descriptor = NULL; | ||
62 | - wildcard->state = CURLWC_DOWNLOADING; | ||
63 | - | ||
64 | - if(Curl_ftp_parselist_geterror(ftpwc->parser)) { | ||
65 | - /* error found in LIST parsing */ | ||
66 | - wildcard->state = CURLWC_CLEAN; | ||
67 | - return wc_statemach(conn); | ||
68 | - } | ||
69 | - if(wildcard->filelist.size == 0) { | ||
70 | - /* no corresponding file */ | ||
71 | - wildcard->state = CURLWC_CLEAN; | ||
72 | - return CURLE_REMOTE_FILE_NOT_FOUND; | ||
73 | + case CURLWC_MATCHING: { | ||
74 | + /* In this state is LIST response successfully parsed, so lets restore | ||
75 | + previous WRITEFUNCTION callback and WRITEDATA pointer */ | ||
76 | + struct ftp_wc *ftpwc = wildcard->protdata; | ||
77 | + conn->data->set.fwrite_func = ftpwc->backup.write_function; | ||
78 | + conn->data->set.out = ftpwc->backup.file_descriptor; | ||
79 | + ftpwc->backup.write_function = ZERO_NULL; | ||
80 | + ftpwc->backup.file_descriptor = NULL; | ||
81 | + wildcard->state = CURLWC_DOWNLOADING; | ||
82 | + | ||
83 | + if(Curl_ftp_parselist_geterror(ftpwc->parser)) { | ||
84 | + /* error found in LIST parsing */ | ||
85 | + wildcard->state = CURLWC_CLEAN; | ||
86 | + continue; | ||
87 | + } | ||
88 | + if(wildcard->filelist.size == 0) { | ||
89 | + /* no corresponding file */ | ||
90 | + wildcard->state = CURLWC_CLEAN; | ||
91 | + return CURLE_REMOTE_FILE_NOT_FOUND; | ||
92 | + } | ||
93 | + continue; | ||
94 | } | ||
95 | - return wc_statemach(conn); | ||
96 | - } | ||
97 | |||
98 | - case CURLWC_DOWNLOADING: { | ||
99 | - /* filelist has at least one file, lets get first one */ | ||
100 | - struct ftp_conn *ftpc = &conn->proto.ftpc; | ||
101 | - struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; | ||
102 | - struct FTP *ftp = conn->data->req.protop; | ||
103 | + case CURLWC_DOWNLOADING: { | ||
104 | + /* filelist has at least one file, lets get first one */ | ||
105 | + struct ftp_conn *ftpc = &conn->proto.ftpc; | ||
106 | + struct curl_fileinfo *finfo = wildcard->filelist.head->ptr; | ||
107 | + struct FTP *ftp = conn->data->req.protop; | ||
108 | |||
109 | - char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); | ||
110 | - if(!tmp_path) | ||
111 | - return CURLE_OUT_OF_MEMORY; | ||
112 | + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); | ||
113 | + if(!tmp_path) | ||
114 | + return CURLE_OUT_OF_MEMORY; | ||
115 | |||
116 | - /* switch default ftp->path and tmp_path */ | ||
117 | - free(ftp->pathalloc); | ||
118 | - ftp->pathalloc = ftp->path = tmp_path; | ||
119 | - | ||
120 | - infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); | ||
121 | - if(conn->data->set.chunk_bgn) { | ||
122 | - long userresponse; | ||
123 | - Curl_set_in_callback(conn->data, true); | ||
124 | - userresponse = conn->data->set.chunk_bgn( | ||
125 | - finfo, wildcard->customptr, (int)wildcard->filelist.size); | ||
126 | - Curl_set_in_callback(conn->data, false); | ||
127 | - switch(userresponse) { | ||
128 | - case CURL_CHUNK_BGN_FUNC_SKIP: | ||
129 | - infof(conn->data, "Wildcard - \"%s\" skipped by user\n", | ||
130 | - finfo->filename); | ||
131 | - wildcard->state = CURLWC_SKIP; | ||
132 | - return wc_statemach(conn); | ||
133 | - case CURL_CHUNK_BGN_FUNC_FAIL: | ||
134 | - return CURLE_CHUNK_FAILED; | ||
135 | + /* switch default ftp->path and tmp_path */ | ||
136 | + free(ftp->pathalloc); | ||
137 | + ftp->pathalloc = ftp->path = tmp_path; | ||
138 | + | ||
139 | + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); | ||
140 | + if(conn->data->set.chunk_bgn) { | ||
141 | + long userresponse; | ||
142 | + Curl_set_in_callback(conn->data, true); | ||
143 | + userresponse = conn->data->set.chunk_bgn( | ||
144 | + finfo, wildcard->customptr, (int)wildcard->filelist.size); | ||
145 | + Curl_set_in_callback(conn->data, false); | ||
146 | + switch(userresponse) { | ||
147 | + case CURL_CHUNK_BGN_FUNC_SKIP: | ||
148 | + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", | ||
149 | + finfo->filename); | ||
150 | + wildcard->state = CURLWC_SKIP; | ||
151 | + continue; | ||
152 | + case CURL_CHUNK_BGN_FUNC_FAIL: | ||
153 | + return CURLE_CHUNK_FAILED; | ||
154 | + } | ||
155 | } | ||
156 | - } | ||
157 | |||
158 | - if(finfo->filetype != CURLFILETYPE_FILE) { | ||
159 | - wildcard->state = CURLWC_SKIP; | ||
160 | - return wc_statemach(conn); | ||
161 | - } | ||
162 | + if(finfo->filetype != CURLFILETYPE_FILE) { | ||
163 | + wildcard->state = CURLWC_SKIP; | ||
164 | + continue; | ||
165 | + } | ||
166 | |||
167 | - if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) | ||
168 | - ftpc->known_filesize = finfo->size; | ||
169 | + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) | ||
170 | + ftpc->known_filesize = finfo->size; | ||
171 | |||
172 | - result = ftp_parse_url_path(conn); | ||
173 | - if(result) | ||
174 | - return result; | ||
175 | + result = ftp_parse_url_path(conn); | ||
176 | + if(result) | ||
177 | + return result; | ||
178 | |||
179 | - /* we don't need the Curl_fileinfo of first file anymore */ | ||
180 | - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); | ||
181 | + /* we don't need the Curl_fileinfo of first file anymore */ | ||
182 | + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); | ||
183 | |||
184 | - if(wildcard->filelist.size == 0) { /* remains only one file to down. */ | ||
185 | - wildcard->state = CURLWC_CLEAN; | ||
186 | - /* after that will be ftp_do called once again and no transfer | ||
187 | - will be done because of CURLWC_CLEAN state */ | ||
188 | - return CURLE_OK; | ||
189 | + if(wildcard->filelist.size == 0) { /* remains only one file to down. */ | ||
190 | + wildcard->state = CURLWC_CLEAN; | ||
191 | + /* after that will be ftp_do called once again and no transfer | ||
192 | + will be done because of CURLWC_CLEAN state */ | ||
193 | + return CURLE_OK; | ||
194 | + } | ||
195 | + return result; | ||
196 | } | ||
197 | - } break; | ||
198 | |||
199 | - case CURLWC_SKIP: { | ||
200 | - if(conn->data->set.chunk_end) { | ||
201 | - Curl_set_in_callback(conn->data, true); | ||
202 | - conn->data->set.chunk_end(conn->data->wildcard.customptr); | ||
203 | - Curl_set_in_callback(conn->data, false); | ||
204 | + case CURLWC_SKIP: { | ||
205 | + if(conn->data->set.chunk_end) { | ||
206 | + Curl_set_in_callback(conn->data, true); | ||
207 | + conn->data->set.chunk_end(conn->data->wildcard.customptr); | ||
208 | + Curl_set_in_callback(conn->data, false); | ||
209 | + } | ||
210 | + Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); | ||
211 | + wildcard->state = (wildcard->filelist.size == 0) ? | ||
212 | + CURLWC_CLEAN : CURLWC_DOWNLOADING; | ||
213 | + continue; | ||
214 | } | ||
215 | - Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL); | ||
216 | - wildcard->state = (wildcard->filelist.size == 0) ? | ||
217 | - CURLWC_CLEAN : CURLWC_DOWNLOADING; | ||
218 | - return wc_statemach(conn); | ||
219 | - } | ||
220 | |||
221 | - case CURLWC_CLEAN: { | ||
222 | - struct ftp_wc *ftpwc = wildcard->protdata; | ||
223 | - result = CURLE_OK; | ||
224 | - if(ftpwc) | ||
225 | - result = Curl_ftp_parselist_geterror(ftpwc->parser); | ||
226 | + case CURLWC_CLEAN: { | ||
227 | + struct ftp_wc *ftpwc = wildcard->protdata; | ||
228 | + result = CURLE_OK; | ||
229 | + if(ftpwc) | ||
230 | + result = Curl_ftp_parselist_geterror(ftpwc->parser); | ||
231 | |||
232 | - wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; | ||
233 | - } break; | ||
234 | + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; | ||
235 | + return result; | ||
236 | + } | ||
237 | |||
238 | - case CURLWC_DONE: | ||
239 | - case CURLWC_ERROR: | ||
240 | - case CURLWC_CLEAR: | ||
241 | - if(wildcard->dtor) | ||
242 | - wildcard->dtor(wildcard->protdata); | ||
243 | - break; | ||
244 | + case CURLWC_DONE: | ||
245 | + case CURLWC_ERROR: | ||
246 | + case CURLWC_CLEAR: | ||
247 | + if(wildcard->dtor) | ||
248 | + wildcard->dtor(wildcard->protdata); | ||
249 | + return result; | ||
250 | + } | ||
251 | } | ||
252 | - | ||
253 | - return result; | ||
254 | + /* UNREACHABLE */ | ||
255 | } | ||
256 | |||
257 | /*********************************************************************** | ||
258 | -- | ||
259 | 2.26.2 | ||
260 | |||
diff --git a/meta/recipes-support/curl/curl/CVE-2020-8286.patch b/meta/recipes-support/curl/curl/CVE-2020-8286.patch new file mode 100644 index 0000000000..093562fe01 --- /dev/null +++ b/meta/recipes-support/curl/curl/CVE-2020-8286.patch | |||
@@ -0,0 +1,133 @@ | |||
1 | From 43d1163b3730f715704240f7f6d31af289246873 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Stenberg <daniel@haxx.se> | ||
3 | Date: Wed, 2 Dec 2020 23:01:11 +0100 | ||
4 | Subject: [PATCH] openssl: make the OCSP verification verify the certificate id | ||
5 | |||
6 | CVE-2020-8286 | ||
7 | |||
8 | Reported by anonymous | ||
9 | |||
10 | Bug: https://curl.se/docs/CVE-2020-8286.html | ||
11 | |||
12 | Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199 | ||
13 | Signed-off-by: Kamil Dudka <kdudka@redhat.com> | ||
14 | |||
15 | Upstream-Status: Backport [import from fedora https://koji.fedoraproject.org/koji/fileinfo?rpmID=24270817&filename=0007-curl-7.71.1-CVE-2020-8286.patch ] | ||
16 | CVE: CVE-2020-8286 | ||
17 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
18 | --- | ||
19 | lib/vtls/openssl.c | 83 ++++++++++++++++++++++++++++++---------------- | ||
20 | 1 file changed, 54 insertions(+), 29 deletions(-) | ||
21 | |||
22 | diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c | ||
23 | index 1d09cad..bcfd83b 100644 | ||
24 | --- a/lib/vtls/openssl.c | ||
25 | +++ b/lib/vtls/openssl.c | ||
26 | @@ -1717,6 +1717,11 @@ static CURLcode verifystatus(struct connectdata *conn, | ||
27 | OCSP_BASICRESP *br = NULL; | ||
28 | X509_STORE *st = NULL; | ||
29 | STACK_OF(X509) *ch = NULL; | ||
30 | + X509 *cert; | ||
31 | + OCSP_CERTID *id = NULL; | ||
32 | + int cert_status, crl_reason; | ||
33 | + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; | ||
34 | + int ret; | ||
35 | |||
36 | long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &status); | ||
37 | |||
38 | @@ -1785,43 +1790,63 @@ static CURLcode verifystatus(struct connectdata *conn, | ||
39 | goto end; | ||
40 | } | ||
41 | |||
42 | - for(i = 0; i < OCSP_resp_count(br); i++) { | ||
43 | - int cert_status, crl_reason; | ||
44 | - OCSP_SINGLERESP *single = NULL; | ||
45 | - | ||
46 | - ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; | ||
47 | + /* Compute the certificate's ID */ | ||
48 | + cert = SSL_get_peer_certificate(BACKEND->handle); | ||
49 | + if(!cert) { | ||
50 | + failf(data, "Error getting peer certficate"); | ||
51 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
52 | + goto end; | ||
53 | + } | ||
54 | |||
55 | - single = OCSP_resp_get0(br, i); | ||
56 | - if(!single) | ||
57 | - continue; | ||
58 | + for(i = 0; i < sk_X509_num(ch); i++) { | ||
59 | + X509 *issuer = sk_X509_value(ch, i); | ||
60 | + if(X509_check_issued(issuer, cert) == X509_V_OK) { | ||
61 | + id = OCSP_cert_to_id(EVP_sha1(), cert, issuer); | ||
62 | + break; | ||
63 | + } | ||
64 | + } | ||
65 | + X509_free(cert); | ||
66 | |||
67 | - cert_status = OCSP_single_get0_status(single, &crl_reason, &rev, | ||
68 | - &thisupd, &nextupd); | ||
69 | + if(!id) { | ||
70 | + failf(data, "Error computing OCSP ID"); | ||
71 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
72 | + goto end; | ||
73 | + } | ||
74 | |||
75 | - if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { | ||
76 | - failf(data, "OCSP response has expired"); | ||
77 | - result = CURLE_SSL_INVALIDCERTSTATUS; | ||
78 | - goto end; | ||
79 | - } | ||
80 | + /* Find the single OCSP response corresponding to the certificate ID */ | ||
81 | + ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev, | ||
82 | + &thisupd, &nextupd); | ||
83 | + OCSP_CERTID_free(id); | ||
84 | + if(ret != 1) { | ||
85 | + failf(data, "Could not find certificate ID in OCSP response"); | ||
86 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
87 | + goto end; | ||
88 | + } | ||
89 | |||
90 | - infof(data, "SSL certificate status: %s (%d)\n", | ||
91 | - OCSP_cert_status_str(cert_status), cert_status); | ||
92 | + /* Validate the corresponding single OCSP response */ | ||
93 | + if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { | ||
94 | + failf(data, "OCSP response has expired"); | ||
95 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
96 | + goto end; | ||
97 | + } | ||
98 | |||
99 | - switch(cert_status) { | ||
100 | - case V_OCSP_CERTSTATUS_GOOD: | ||
101 | - break; | ||
102 | + infof(data, "SSL certificate status: %s (%d)\n", | ||
103 | + OCSP_cert_status_str(cert_status), cert_status); | ||
104 | |||
105 | - case V_OCSP_CERTSTATUS_REVOKED: | ||
106 | - result = CURLE_SSL_INVALIDCERTSTATUS; | ||
107 | + switch(cert_status) { | ||
108 | + case V_OCSP_CERTSTATUS_GOOD: | ||
109 | + break; | ||
110 | |||
111 | - failf(data, "SSL certificate revocation reason: %s (%d)", | ||
112 | - OCSP_crl_reason_str(crl_reason), crl_reason); | ||
113 | - goto end; | ||
114 | + case V_OCSP_CERTSTATUS_REVOKED: | ||
115 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
116 | + failf(data, "SSL certificate revocation reason: %s (%d)", | ||
117 | + OCSP_crl_reason_str(crl_reason), crl_reason); | ||
118 | + goto end; | ||
119 | |||
120 | - case V_OCSP_CERTSTATUS_UNKNOWN: | ||
121 | - result = CURLE_SSL_INVALIDCERTSTATUS; | ||
122 | - goto end; | ||
123 | - } | ||
124 | + case V_OCSP_CERTSTATUS_UNKNOWN: | ||
125 | + default: | ||
126 | + result = CURLE_SSL_INVALIDCERTSTATUS; | ||
127 | + goto end; | ||
128 | } | ||
129 | |||
130 | end: | ||
131 | -- | ||
132 | 2.26.2 | ||
133 | |||
diff --git a/meta/recipes-support/curl/curl_7.69.1.bb b/meta/recipes-support/curl/curl_7.69.1.bb index 239852db09..c3d629108a 100644 --- a/meta/recipes-support/curl/curl_7.69.1.bb +++ b/meta/recipes-support/curl/curl_7.69.1.bb | |||
@@ -9,6 +9,10 @@ SRC_URI = "https://curl.haxx.se/download/curl-${PV}.tar.bz2 \ | |||
9 | file://0001-replace-krb5-config-with-pkg-config.patch \ | 9 | file://0001-replace-krb5-config-with-pkg-config.patch \ |
10 | file://CVE-2020-8169.patch \ | 10 | file://CVE-2020-8169.patch \ |
11 | file://CVE-2020-8177.patch \ | 11 | file://CVE-2020-8177.patch \ |
12 | file://CVE-2020-8231.patch \ | ||
13 | file://CVE-2020-8284.patch \ | ||
14 | file://CVE-2020-8285.patch \ | ||
15 | file://CVE-2020-8286.patch \ | ||
12 | " | 16 | " |
13 | 17 | ||
14 | SRC_URI[md5sum] = "ec5fc263f898a3dfef08e805f1ecca42" | 18 | SRC_URI[md5sum] = "ec5fc263f898a3dfef08e805f1ecca42" |