diff --git a/0004-curl-7.59.0-http2-GOAWAY.patch b/0004-curl-7.59.0-http2-GOAWAY.patch new file mode 100644 index 0000000..0e76a6e --- /dev/null +++ b/0004-curl-7.59.0-http2-GOAWAY.patch @@ -0,0 +1,137 @@ +From 84ddda3994c1f12d79946780dee9111b3cf1c308 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 19 Apr 2018 20:03:30 +0200 +Subject: [PATCH] http2: handle GOAWAY properly + +When receiving REFUSED_STREAM, mark the connection for close and retry +streams accordingly on another/fresh connection. + +Reported-by: Terry Wu +Fixes #2416 +Fixes #1618 +Closes #2510 + +Upstream-commit: d122df5972fc01e39ae28e6bca705237d7e3318a +Signed-off-by: Kamil Dudka +--- + lib/http2.c | 17 ++++++++++++----- + lib/multi.c | 4 +++- + lib/transfer.c | 17 +++++++++++++++-- + lib/urldata.h | 2 +- + 4 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/lib/http2.c b/lib/http2.c +index b2c34e9..fba4d70 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -1078,7 +1078,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature) + struct http_conn *httpc = &conn->proto.httpc; + + if(http->header_recvbuf) { +- H2BUGF(infof(data, "free header_recvbuf!!\n")); + Curl_add_buffer_free(http->header_recvbuf); + http->header_recvbuf = NULL; /* clear the pointer */ + Curl_add_buffer_free(http->trailer_recvbuf); +@@ -1351,7 +1350,15 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, + + /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ + stream->closed = FALSE; +- if(httpc->error_code != NGHTTP2_NO_ERROR) { ++ if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { ++ H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", ++ stream->stream_id)); ++ connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ ++ data->state.refused_stream = TRUE; ++ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ ++ return -1; ++ } ++ else if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)", + stream->stream_id, Curl_http2_strerror(httpc->error_code), + httpc->error_code); +@@ -1579,9 +1586,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, + } + + if(nread == 0) { +- failf(data, "Unexpected EOF"); +- *err = CURLE_RECV_ERROR; +- return -1; ++ H2BUGF(infof(data, "end of stream\n")); ++ *err = CURLE_OK; ++ return 0; + } + + H2BUGF(infof(data, "nread=%zd\n", nread)); +diff --git a/lib/multi.c b/lib/multi.c +index 98e5fca..d69e5f9 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -541,7 +541,9 @@ static CURLcode multi_done(struct connectdata **connp, + if(conn->send_pipe.size || conn->recv_pipe.size) { + /* Stop if pipeline is not empty . */ + data->easy_conn = NULL; +- DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n")); ++ DEBUGF(infof(data, "Connection still in use %d/%d, " ++ "no more multi_done now!\n", ++ conn->send_pipe.size, conn->recv_pipe.size)); + return CURLE_OK; + } + +diff --git a/lib/transfer.c b/lib/transfer.c +index fd9af31..5c29cc9 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1926,7 +1926,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, + char **url) + { + struct Curl_easy *data = conn->data; +- ++ bool retry = FALSE; + *url = NULL; + + /* if we're talking upload, we can't do the checks below, unless the protocol +@@ -1939,7 +1939,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, + conn->bits.reuse && + (!data->set.opt_no_body + || (conn->handler->protocol & PROTO_FAMILY_HTTP)) && +- (data->set.rtspreq != RTSPREQ_RECEIVE)) { ++ (data->set.rtspreq != RTSPREQ_RECEIVE)) + /* We got no data, we attempted to re-use a connection. For HTTP this + can be a retry so we try again regardless if we expected a body. + For other protocols we only try again only if we expected a body. +@@ -1947,6 +1947,19 @@ CURLcode Curl_retry_request(struct connectdata *conn, + This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ ++ retry = TRUE; ++ else if(data->state.refused_stream && ++ (data->req.bytecount + data->req.headerbytecount == 0) ) { ++ /* This was sent on a refused stream, safe to rerun. A refused stream ++ error can typically only happen on HTTP/2 level if the stream is safe ++ to issue again, but the nghttp2 API can deliver the message to other ++ streams as well, which is why this adds the check the data counters ++ too. */ ++ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n"); ++ data->state.refused_stream = FALSE; /* clear again */ ++ retry = TRUE; ++ } ++ if(retry) { + infof(conn->data, "Connection died, retrying a fresh connect\n"); + *url = strdup(conn->data->change.url); + if(!*url) +diff --git a/lib/urldata.h b/lib/urldata.h +index 3d7b9e5..6a36ee9 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1225,7 +1225,7 @@ struct UrlState { + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ + bool this_is_a_follow; /* this is a followed Location: request */ +- ++ bool refused_stream; /* this was refused, try again */ + char *first_host; /* host name of the first (not followed) request. + if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: +-- +2.14.4 + diff --git a/curl.spec b/curl.spec index 904ba10..abf84a4 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.59.0 -Release: 3%{?dist} +Release: 4%{?dist} License: MIT Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz @@ -14,6 +14,9 @@ Patch2: 0002-curl-7.59.0-CVE-2018-1000301.patch # fix FTP shutdown response buffer overflow (CVE-2018-1000300) Patch3: 0003-curl-7.59.0-CVE-2018-1000300.patch +# http2: handle GOAWAY properly (#1585797) +Patch4: 0004-curl-7.59.0-http2-GOAWAY.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -163,6 +166,7 @@ be installed. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 # Fedora patches %patch101 -p1 @@ -308,6 +312,9 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.4.[0-9].[0-9].minimal %changelog +* Tue Jun 05 2018 Kamil Dudka - 7.59.0-4 +- http2: handle GOAWAY properly (#1585797) + * Fri May 18 2018 Kamil Dudka - 7.59.0-3 - fix FTP shutdown response buffer overflow (CVE-2018-1000300) - fix RTSP bad headers buffer over-read (CVE-2018-1000301)