Resolves: CVE-2020-8231 - libcurl: wrong connect-only connection
This commit is contained in:
parent
840be82e6f
commit
2c28dfb932
281
0004-curl-7.71.1-CVE-2020-8231.patch
Normal file
281
0004-curl-7.71.1-CVE-2020-8231.patch
Normal file
@ -0,0 +1,281 @@
|
||||
From 6830828c9eecd9ab14404f2f49f19b56dec62130 Mon Sep 17 00:00:00 2001
|
||||
From: Marc Aldorasi <marc@groundctl.com>
|
||||
Date: Thu, 30 Jul 2020 14:16:17 -0400
|
||||
Subject: [PATCH 1/2] multi_remove_handle: close unused connect-only
|
||||
connections
|
||||
|
||||
Previously any connect-only connections in a multi handle would be kept
|
||||
alive until the multi handle was closed. Since these connections cannot
|
||||
be re-used, they can be marked for closure when the associated easy
|
||||
handle is removed from the multi handle.
|
||||
|
||||
Closes #5749
|
||||
|
||||
Upstream-commit: d5bb459ccf1fc5980ae4b95c05b4ecf6454a7599
|
||||
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||||
---
|
||||
lib/multi.c | 34 ++++++++++++++++++++++++++++++----
|
||||
tests/data/test1554 | 6 ++++++
|
||||
2 files changed, 36 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/multi.c b/lib/multi.c
|
||||
index 249e360..f1371bd 100644
|
||||
--- a/lib/multi.c
|
||||
+++ b/lib/multi.c
|
||||
@@ -689,6 +689,26 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
+static int close_connect_only(struct connectdata *conn, void *param)
|
||||
+{
|
||||
+ struct Curl_easy *data = param;
|
||||
+
|
||||
+ if(data->state.lastconnect != conn)
|
||||
+ return 0;
|
||||
+
|
||||
+ if(conn->data != data)
|
||||
+ return 1;
|
||||
+ conn->data = NULL;
|
||||
+
|
||||
+ if(!conn->bits.connect_only)
|
||||
+ return 1;
|
||||
+
|
||||
+ connclose(conn, "Removing connect-only easy handle");
|
||||
+ conn->bits.connect_only = FALSE;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
@@ -776,10 +796,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
multi_done() as that may actually call Curl_expire that uses this */
|
||||
Curl_llist_destroy(&data->state.timeoutlist, NULL);
|
||||
|
||||
- /* as this was using a shared connection cache we clear the pointer to that
|
||||
- since we're not part of that multi handle anymore */
|
||||
- data->state.conn_cache = NULL;
|
||||
-
|
||||
/* change state without using multistate(), only to make singlesocket() do
|
||||
what we want */
|
||||
data->mstate = CURLM_STATE_COMPLETED;
|
||||
@@ -789,12 +805,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
/* Remove the association between the connection and the handle */
|
||||
Curl_detach_connnection(data);
|
||||
|
||||
+ if(data->state.lastconnect) {
|
||||
+ /* Mark any connect-only connection for closure */
|
||||
+ Curl_conncache_foreach(data, data->state.conn_cache,
|
||||
+ data, &close_connect_only);
|
||||
+ }
|
||||
+
|
||||
#ifdef USE_LIBPSL
|
||||
/* Remove the PSL association. */
|
||||
if(data->psl == &multi->psl)
|
||||
data->psl = NULL;
|
||||
#endif
|
||||
|
||||
+ /* as this was using a shared connection cache we clear the pointer to that
|
||||
+ since we're not part of that multi handle anymore */
|
||||
+ data->state.conn_cache = NULL;
|
||||
+
|
||||
data->multi = NULL; /* clear the association to this multi handle */
|
||||
|
||||
/* make sure there's no pending message in the queue sent from this easy
|
||||
diff --git a/tests/data/test1554 b/tests/data/test1554
|
||||
index d3926d9..fffa6ad 100644
|
||||
--- a/tests/data/test1554
|
||||
+++ b/tests/data/test1554
|
||||
@@ -50,6 +50,8 @@ run 1: foobar and so on fun!
|
||||
<- Mutex unlock
|
||||
-> Mutex lock
|
||||
<- Mutex unlock
|
||||
+-> Mutex lock
|
||||
+<- Mutex unlock
|
||||
run 1: foobar and so on fun!
|
||||
-> Mutex lock
|
||||
<- Mutex unlock
|
||||
@@ -65,6 +67,8 @@ run 1: foobar and so on fun!
|
||||
<- Mutex unlock
|
||||
-> Mutex lock
|
||||
<- Mutex unlock
|
||||
+-> Mutex lock
|
||||
+<- Mutex unlock
|
||||
run 1: foobar and so on fun!
|
||||
-> Mutex lock
|
||||
<- Mutex unlock
|
||||
@@ -74,6 +78,8 @@ run 1: foobar and so on fun!
|
||||
<- Mutex unlock
|
||||
-> Mutex lock
|
||||
<- Mutex unlock
|
||||
+-> Mutex lock
|
||||
+<- Mutex unlock
|
||||
</datacheck>
|
||||
</reply>
|
||||
|
||||
--
|
||||
2.25.4
|
||||
|
||||
|
||||
From 01148ee40dd913a169435b0f9ea90e6393821e70 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stenberg <daniel@haxx.se>
|
||||
Date: Sun, 16 Aug 2020 11:34:35 +0200
|
||||
Subject: [PATCH 2/2] Curl_easy: remember last connection by id, not by pointer
|
||||
|
||||
CVE-2020-8231
|
||||
|
||||
Bug: https://curl.haxx.se/docs/CVE-2020-8231.html
|
||||
|
||||
Reported-by: Marc Aldorasi
|
||||
Closes #5824
|
||||
|
||||
Upstream-commit: 3c9e021f86872baae412a427e807fbfa2f3e8a22
|
||||
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
||||
---
|
||||
lib/connect.c | 19 ++++++++++---------
|
||||
lib/easy.c | 3 +--
|
||||
lib/multi.c | 9 +++++----
|
||||
lib/url.c | 2 +-
|
||||
lib/urldata.h | 2 +-
|
||||
5 files changed, 18 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/lib/connect.c b/lib/connect.c
|
||||
index 29293f0..e1c5662 100644
|
||||
--- a/lib/connect.c
|
||||
+++ b/lib/connect.c
|
||||
@@ -1363,15 +1363,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
}
|
||||
|
||||
struct connfind {
|
||||
- struct connectdata *tofind;
|
||||
- bool found;
|
||||
+ long id_tofind;
|
||||
+ struct connectdata *found;
|
||||
};
|
||||
|
||||
static int conn_is_conn(struct connectdata *conn, void *param)
|
||||
{
|
||||
struct connfind *f = (struct connfind *)param;
|
||||
- if(conn == f->tofind) {
|
||||
- f->found = TRUE;
|
||||
+ if(conn->connection_id == f->id_tofind) {
|
||||
+ f->found = conn;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1393,21 +1393,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
* - that is associated with a multi handle, and whose connection
|
||||
* was detached with CURLOPT_CONNECT_ONLY
|
||||
*/
|
||||
- if(data->state.lastconnect && (data->multi_easy || data->multi)) {
|
||||
- struct connectdata *c = data->state.lastconnect;
|
||||
+ if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
|
||||
+ struct connectdata *c;
|
||||
struct connfind find;
|
||||
- find.tofind = data->state.lastconnect;
|
||||
- find.found = FALSE;
|
||||
+ find.id_tofind = data->state.lastconnect_id;
|
||||
+ find.found = NULL;
|
||||
|
||||
Curl_conncache_foreach(data, data->multi_easy?
|
||||
&data->multi_easy->conn_cache:
|
||||
&data->multi->conn_cache, &find, conn_is_conn);
|
||||
|
||||
if(!find.found) {
|
||||
- data->state.lastconnect = NULL;
|
||||
+ data->state.lastconnect_id = -1;
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
+ c = find.found;
|
||||
if(connp) {
|
||||
/* only store this if the caller cares for it */
|
||||
*connp = c;
|
||||
diff --git a/lib/easy.c b/lib/easy.c
|
||||
index 292cca7..a69eb9e 100644
|
||||
--- a/lib/easy.c
|
||||
+++ b/lib/easy.c
|
||||
@@ -838,8 +838,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
|
||||
/* the connection cache is setup on demand */
|
||||
outcurl->state.conn_cache = NULL;
|
||||
-
|
||||
- outcurl->state.lastconnect = NULL;
|
||||
+ outcurl->state.lastconnect_id = -1;
|
||||
|
||||
outcurl->progress.flags = data->progress.flags;
|
||||
outcurl->progress.callback = data->progress.callback;
|
||||
diff --git a/lib/multi.c b/lib/multi.c
|
||||
index f1371bd..778c537 100644
|
||||
--- a/lib/multi.c
|
||||
+++ b/lib/multi.c
|
||||
@@ -455,6 +455,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
data->state.conn_cache = &data->share->conn_cache;
|
||||
else
|
||||
data->state.conn_cache = &multi->conn_cache;
|
||||
+ data->state.lastconnect_id = -1;
|
||||
|
||||
#ifdef USE_LIBPSL
|
||||
/* Do the same for PSL. */
|
||||
@@ -677,11 +678,11 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
CONNCACHE_UNLOCK(data);
|
||||
if(Curl_conncache_return_conn(data, conn)) {
|
||||
/* remember the most recently used connection */
|
||||
- data->state.lastconnect = conn;
|
||||
+ data->state.lastconnect_id = conn->connection_id;
|
||||
infof(data, "%s\n", buffer);
|
||||
}
|
||||
else
|
||||
- data->state.lastconnect = NULL;
|
||||
+ data->state.lastconnect_id = -1;
|
||||
}
|
||||
|
||||
Curl_safefree(data->state.buffer);
|
||||
@@ -693,7 +694,7 @@ static int close_connect_only(struct connectdata *conn, void *param)
|
||||
{
|
||||
struct Curl_easy *data = param;
|
||||
|
||||
- if(data->state.lastconnect != conn)
|
||||
+ if(data->state.lastconnect_id != conn->connection_id)
|
||||
return 0;
|
||||
|
||||
if(conn->data != data)
|
||||
@@ -805,7 +806,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
|
||||
/* Remove the association between the connection and the handle */
|
||||
Curl_detach_connnection(data);
|
||||
|
||||
- if(data->state.lastconnect) {
|
||||
+ if(data->state.lastconnect_id != -1) {
|
||||
/* Mark any connect-only connection for closure */
|
||||
Curl_conncache_foreach(data, data->state.conn_cache,
|
||||
data, &close_connect_only);
|
||||
diff --git a/lib/url.c b/lib/url.c
|
||||
index a1a6b69..2919a3d 100644
|
||||
--- a/lib/url.c
|
||||
+++ b/lib/url.c
|
||||
@@ -630,7 +630,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
Curl_initinfo(data);
|
||||
|
||||
/* most recent connection is not yet defined */
|
||||
- data->state.lastconnect = NULL;
|
||||
+ data->state.lastconnect_id = -1;
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
diff --git a/lib/urldata.h b/lib/urldata.h
|
||||
index f80a02d..6d8eb69 100644
|
||||
--- a/lib/urldata.h
|
||||
+++ b/lib/urldata.h
|
||||
@@ -1300,7 +1300,7 @@ struct UrlState {
|
||||
/* buffers to store authentication data in, as parsed from input options */
|
||||
struct curltime keeps_speed; /* for the progress meter really */
|
||||
|
||||
- struct connectdata *lastconnect; /* The last connection, NULL if undefined */
|
||||
+ long lastconnect_id; /* The last connection, -1 if undefined */
|
||||
struct dynbuf headerb; /* buffer to store headers in */
|
||||
|
||||
char *buffer; /* download buffer */
|
||||
--
|
||||
2.25.4
|
||||
|
@ -1,7 +1,7 @@
|
||||
Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
|
||||
Name: curl
|
||||
Version: 7.71.1
|
||||
Release: 5%{?dist}
|
||||
Release: 6%{?dist}
|
||||
License: MIT
|
||||
Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz
|
||||
|
||||
@ -11,6 +11,9 @@ Patch1: 0001-curl-7.71.1-tool-krb-opt.patch
|
||||
# setopt: unset NOBODY switches to GET if still HEAD
|
||||
Patch2: 0002-curl-7.71.1-unset-nobody.patch
|
||||
|
||||
# libcurl: wrong connect-only connection (CVE-2020-8231)
|
||||
Patch4: 0004-curl-7.71.1-CVE-2020-8231.patch
|
||||
|
||||
# patch making libcurl multilib ready
|
||||
Patch101: 0101-curl-7.32.0-multilib.patch
|
||||
|
||||
@ -180,6 +183,7 @@ be installed.
|
||||
# upstream patches
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch4 -p1
|
||||
|
||||
# Fedora patches
|
||||
%patch101 -p1
|
||||
@ -358,6 +362,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
|
||||
%{_libdir}/libcurl.so.4.[0-9].[0-9].minimal
|
||||
|
||||
%changelog
|
||||
* Wed Aug 19 2020 Kamil Dudka <kdudka@redhat.com> - 7.71.1-6
|
||||
- libcurl: wrong connect-only connection (CVE-2020-8231)
|
||||
|
||||
* Thu Aug 06 2020 Kamil Dudka <kdudka@redhat.com> - 7.71.1-5
|
||||
- setopt: unset NOBODY switches to GET if still HEAD
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user