diff --git a/0057-curl-7.61.1-consolidate-nghttp2-session-mem-recv.patch b/0057-curl-7.61.1-consolidate-nghttp2-session-mem-recv.patch new file mode 100644 index 0000000..c6ffea9 --- /dev/null +++ b/0057-curl-7.61.1-consolidate-nghttp2-session-mem-recv.patch @@ -0,0 +1,193 @@ +diff -up curl-7.61.1/lib/http2.c.25a25f45 curl-7.61.1/lib/http2.c +--- curl-7.61.1/lib/http2.c.25a25f45 2023-08-07 14:03:42.043463284 +0200 ++++ curl-7.61.1/lib/http2.c 2023-08-07 14:10:24.769489855 +0200 +@@ -1202,7 +1202,7 @@ CURLcode Curl_http2_request_upgrade(Curl + binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, + httpc->local_settings, + httpc->local_settings_num); +- if(!binlen) { ++ if(binlen <= 0) { + failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload"); + Curl_add_buffer_free(req); + return CURLE_FAILED_INIT; +@@ -1285,6 +1285,14 @@ static int h2_process_pending_input(stru + return -1; + } + ++ if(nghttp2_session_check_request_allowed(httpc->h2) == 0) { ++ /* No more requests are allowed in the current session, so ++ the connection may not be reused. This is set when a ++ GOAWAY frame has been received or when the limit of stream ++ identifiers has been reached. */ ++ connclose(conn, "http/2: No new requests allowed"); ++ } ++ + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "h2_process_pending_input: nothing to do in this session\n")); +@@ -1297,7 +1305,6 @@ static int h2_process_pending_input(stru + } + return -1; + } +- + return 0; + } + +@@ -1455,8 +1462,6 @@ static int h2_session_send(struct Curl_e + static ssize_t http2_recv(struct connectdata *conn, int sockindex, + char *mem, size_t len, CURLcode *err) + { +- CURLcode result = CURLE_OK; +- ssize_t rv; + ssize_t nread; + struct http_conn *httpc = &conn->proto.httpc; + struct Curl_easy *data = conn->data; +@@ -1519,8 +1524,7 @@ static ssize_t http2_recv(struct connect + /* We have paused nghttp2, but we have no pause data (see + on_data_chunk_recv). */ + httpc->pause_stream_id = 0; +- if(h2_process_pending_input(conn, httpc, &result) != 0) { +- *err = result; ++ if(h2_process_pending_input(conn, httpc, err) != 0) { + return -1; + } + } +@@ -1549,8 +1553,7 @@ static ssize_t http2_recv(struct connect + frames, then we have to call it again with 0-length data. + Without this, on_stream_close callback will not be called, + and stream could be hanged. */ +- if(h2_process_pending_input(conn, httpc, &result) != 0) { +- *err = result; ++ if(h2_process_pending_input(conn, httpc, err) != 0) { + return -1; + } + } +@@ -1573,7 +1576,6 @@ static ssize_t http2_recv(struct connect + return -1; + } + else { +- char *inbuf; + /* remember where to store incoming data for this stream and how big the + buffer is */ + stream->mem = mem; +@@ -1582,16 +1584,15 @@ static ssize_t http2_recv(struct connect + + if(httpc->inbuflen == 0) { + nread = ((Curl_recv *)httpc->recv_underlying)( +- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); ++ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err); + + if(nread == -1) { +- if(result != CURLE_AGAIN) ++ if(*err != CURLE_AGAIN) + failf(data, "Failed receiving HTTP2 data"); + else if(stream->closed) + /* received when the stream was already closed! */ + return http2_handle_stream_close(conn, data, stream, err); + +- *err = result; + return -1; + } + +@@ -1604,47 +1605,17 @@ static ssize_t http2_recv(struct connect + H2BUGF(infof(data, "nread=%zd\n", nread)); + + httpc->inbuflen = nread; +- inbuf = httpc->inbuf; ++ ++ DEBUGASSERT(httpc->nread_inbuf == 0); + } + else { + nread = httpc->inbuflen - httpc->nread_inbuf; +- inbuf = httpc->inbuf + httpc->nread_inbuf; +- ++ (void)nread; /* silence warning, used in debug */ + H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", + nread)); + } +- rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread); +- +- if(nghttp2_is_fatal((int)rv)) { +- failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n", +- rv, nghttp2_strerror((int)rv)); +- *err = CURLE_RECV_ERROR; +- return -1; +- } +- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv)); +- if(nread == rv) { +- H2BUGF(infof(data, "All data in connection buffer processed\n")); +- httpc->inbuflen = 0; +- httpc->nread_inbuf = 0; +- } +- else { +- httpc->nread_inbuf += rv; +- H2BUGF(infof(data, "%zu bytes left in connection buffer\n", +- httpc->inbuflen - httpc->nread_inbuf)); +- } +- /* Always send pending frames in nghttp2 session, because +- nghttp2_session_mem_recv() may queue new frame */ +- rv = h2_session_send(data, httpc->h2); +- if(rv != 0) { +- *err = CURLE_SEND_ERROR; +- return -1; +- } +- +- if(should_close_session(httpc)) { +- H2BUGF(infof(data, "http2_recv: nothing to do in this session\n")); +- *err = CURLE_HTTP2; ++ if(h2_process_pending_input(conn, httpc, err) != 0) + return -1; +- } + } + if(stream->memlen) { + ssize_t retlen = stream->memlen; +@@ -2108,7 +2079,6 @@ CURLcode Curl_http2_switched(struct conn + CURLcode result; + struct http_conn *httpc = &conn->proto.httpc; + int rv; +- ssize_t nproc; + struct Curl_easy *data = conn->data; + struct HTTP *stream = conn->data->req.protop; + +@@ -2186,39 +2156,10 @@ CURLcode Curl_http2_switched(struct conn + memcpy(httpc->inbuf, mem, nread); + httpc->inbuflen = nread; + +- nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, +- httpc->inbuflen); ++ DEBUGASSERT(httpc->nread_inbuf == 0); + +- if(nghttp2_is_fatal((int)nproc)) { +- failf(data, "nghttp2_session_mem_recv() failed: %s(%d)", +- nghttp2_strerror((int)nproc), (int)nproc); ++ if(-1 == h2_process_pending_input(conn, httpc, &result)) + return CURLE_HTTP2; +- } +- +- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc)); +- +- if((ssize_t)nread == nproc) { +- httpc->inbuflen = 0; +- httpc->nread_inbuf = 0; +- } +- else { +- httpc->nread_inbuf += nproc; +- } +- +- /* Try to send some frames since we may read SETTINGS already. */ +- rv = h2_session_send(data, httpc->h2); +- +- if(rv != 0) { +- failf(data, "nghttp2_session_send() failed: %s(%d)", +- nghttp2_strerror(rv), rv); +- return CURLE_HTTP2; +- } +- +- if(should_close_session(httpc)) { +- H2BUGF(infof(data, +- "nghttp2_session_send(): nothing to do in this session\n")); +- return CURLE_HTTP2; +- } + + return CURLE_OK; + } diff --git a/0058-curl-7.61.1-error-in-the-HTTP2-framing-layer.patch b/0058-curl-7.61.1-error-in-the-HTTP2-framing-layer.patch new file mode 100644 index 0000000..5dc8ada --- /dev/null +++ b/0058-curl-7.61.1-error-in-the-HTTP2-framing-layer.patch @@ -0,0 +1,15 @@ +diff -up curl-7.61.1/lib/http2.c.c1b6a384 curl-7.61.1/lib/http2.c +--- curl-7.61.1/lib/http2.c.c1b6a384 2023-08-07 13:59:18.482137005 +0200 ++++ curl-7.61.1/lib/http2.c 2023-08-07 14:03:42.043463284 +0200 +@@ -1467,6 +1467,11 @@ static ssize_t http2_recv(struct connect + if(should_close_session(httpc)) { + H2BUGF(infof(data, + "http2_recv: nothing to do in this session\n")); ++ if(conn->bits.close) { ++ /* already marked for closure, return OK and we're done */ ++ *err = CURLE_OK; ++ return 0; ++ } + *err = CURLE_HTTP2; + return -1; + } diff --git a/curl.spec b/curl.spec index 2641155..8e55a43 100644 --- a/curl.spec +++ b/curl.spec @@ -163,6 +163,12 @@ Patch55: 0055-curl-7.61.1-CVE-2023-28322.patch # fix cookie injection with none file (CVE-2023-38546) Patch56: 0056-curl-7.61.1-CVE-2023-38546.patch +# consolidate nghttp2_session_mem_recv() call paths +Patch57: 0057-curl-7.61.1-consolidate-nghttp2-session-mem-recv.patch + +# when marked for closure and wanted to close == OK +Patch58: 0058-curl-7.61.1-error-in-the-HTTP2-framing-layer.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -392,6 +398,8 @@ git apply %{PATCH52} %patch54 -p1 %patch55 -p1 %patch56 -p1 +%patch57 -p1 +%patch58 -p1 # make tests/*.py use Python 3 sed -e '1 s|^#!/.*python|#!%{__python3}|' -i tests/*.py @@ -559,6 +567,7 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la - cap SFTP packet size sent (RHEL-5311) - unify the upload/method handling (CVE-2023-28322) - fix cookie injection with none file (CVE-2023-38546) +- fix HTTP2 connection failure with HTTP2 framing layer (RHEL-5657) * Tue Jun 27 2023 Jacek Migacz - 7.61.1-33 - fix host name wildcard checking (CVE-2023-28321)