From 5989d6e452e7a2bc7afac6c282072c16140592b8 Mon Sep 17 00:00:00 2001 From: Nishant Chaprana Date: Sat, 9 Mar 2019 12:11:38 +0530 Subject: [PATCH 01/16] smtp: avoid risk of buffer overflow in strtol If the incoming len 5, but the buffer does not have a termination after 5 bytes, the strtol() call may keep reading through the line buffer until is exceeds its boundary. Fix by ensuring that we are using a bounded read with a temporary buffer on the stack. Bug: https://curl.haxx.se/docs/CVE-2019-3823.html Reported-by: Brian Carpenter (Geeknik Labs) CVE-2019-3823 Backported patch details:- Link: https://github.com/curl/curl/commit/39df4073e5413fcdbb5a38da0c1ce6f1c0ceb484.patch Change-Id: Ie00a759a464e51ded79d2288844053740db055b4 Signed-off-by: Nishant Chaprana --- lib/smtp.c | 8 ++++++-- packaging/curl.spec | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/smtp.c b/lib/smtp.c index 587562306..16ec3e426 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -207,8 +207,12 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, Section 4. Examples of RFC-4954 but some e-mail servers ignore this and only send the response code instead as per Section 4.2. */ if(line[3] == ' ' || len == 5) { + char tmpline[6]; + result = TRUE; - *resp = curlx_sltosi(strtol(line, NULL, 10)); + memset(tmpline, '\0', sizeof(tmpline)); + memcpy(tmpline, line, (len == 5 ? 5 : 3)); + *resp = curlx_sltosi(strtol(tmpline, NULL, 10)); /* Make sure real server never sends internal value */ if(*resp == 1) diff --git a/packaging/curl.spec b/packaging/curl.spec index a07af8aa6..591503ebb 100644 --- a/packaging/curl.spec +++ b/packaging/curl.spec @@ -1,7 +1,7 @@ Name: curl Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Version: 7.62.0 -Release: 1 +Release: 2 Group: Applications/Internet License: MIT URL: http://curl.haxx.se/ -- 2.34.1 From e57a422322fb42574ae27ad1eb72997646b578b4 Mon Sep 17 00:00:00 2001 From: Nishant Chaprana Date: Sat, 9 Mar 2019 12:15:26 +0530 Subject: [PATCH 02/16] ntlm: fix *_type3_message size check to avoid buffer overflow Bug: https://curl.haxx.se/docs/CVE-2019-3822.html Reported-by: Wenxiang Qian CVE-2019-3822 Backported patch details:- Link: https://github.com/curl/curl/commit/50c9484278c63b958655a717844f0721263939cc.patch Change-Id: I40a37af26b81a4cefe4a26f19697e7a73b17eaf6 Signed-off-by: Nishant Chaprana --- lib/vauth/ntlm.c | 11 +++++++---- packaging/curl.spec | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index 11f42f504..82b59f61d 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -776,11 +776,14 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, }); #ifdef USE_NTRESPONSES - if(size < (NTLM_BUFSIZE - ntresplen)) { - DEBUGASSERT(size == (size_t)ntrespoff); - memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); - size += ntresplen; + /* ntresplen + size should not be risking an integer overflow here */ + if(ntresplen + size > sizeof(ntlmbuf)) { + failf(data, "incoming NTLM message too big"); + return CURLE_OUT_OF_MEMORY; } + DEBUGASSERT(size == (size_t)ntrespoff); + memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); + size += ntresplen; DEBUG_OUT({ fprintf(stderr, "\n ntresp="); diff --git a/packaging/curl.spec b/packaging/curl.spec index 591503ebb..42a93baea 100644 --- a/packaging/curl.spec +++ b/packaging/curl.spec @@ -1,7 +1,7 @@ Name: curl Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Version: 7.62.0 -Release: 2 +Release: 3 Group: Applications/Internet License: MIT URL: http://curl.haxx.se/ -- 2.34.1 From ce2c30a81630cdc9f58f31424394f418c2ea4de5 Mon Sep 17 00:00:00 2001 From: Nishant Chaprana Date: Sat, 9 Mar 2019 12:21:06 +0530 Subject: [PATCH 03/16] NTLM: fix size check condition for type2 received data Bug: https://curl.haxx.se/docs/CVE-2018-16890.html Reported-by: Wenxiang Qian CVE-2018-16890 Backported patch details:- Link: https://github.com/curl/curl/commit/b780b30d1377adb10bbe774835f49e9b237fb9bb.patch Change-Id: I15fc8002280680a7cf194dd02a5d7751cc7dbc71 Signed-off-by: Nishant Chaprana --- lib/vauth/ntlm.c | 7 ++++--- packaging/curl.spec | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index 82b59f61d..1bef9ee38 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -182,10 +182,11 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, target_info_len = Curl_read16_le(&buffer[40]); target_info_offset = Curl_read32_le(&buffer[44]); if(target_info_len > 0) { - if(((target_info_offset + target_info_len) > size) || + if((target_info_offset >= size) || + ((target_info_offset + target_info_len) > size) || (target_info_offset < 48)) { infof(data, "NTLM handshake failure (bad type-2 message). " - "Target Info Offset Len is set incorrect by the peer\n"); + "Target Info Offset Len is set incorrect by the peer\n"); return CURLE_BAD_CONTENT_ENCODING; } diff --git a/packaging/curl.spec b/packaging/curl.spec index 42a93baea..8e4f44789 100644 --- a/packaging/curl.spec +++ b/packaging/curl.spec @@ -1,7 +1,7 @@ Name: curl Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Version: 7.62.0 -Release: 3 +Release: 4 Group: Applications/Internet License: MIT URL: http://curl.haxx.se/ -- 2.34.1 From 6b333876d2db240bd01e0dcec950b2d12dc8eae5 Mon Sep 17 00:00:00 2001 From: Cheoleun Moon Date: Tue, 7 May 2019 17:46:36 +0900 Subject: [PATCH 04/16] Use openssl-1.1 Change-Id: I152d19a11c8bd12e63c3e573bba73668262099e8 Signed-off-by: Cheoleun Moon --- packaging/curl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/curl.spec b/packaging/curl.spec index 8e4f44789..f0572490c 100644 --- a/packaging/curl.spec +++ b/packaging/curl.spec @@ -10,7 +10,7 @@ Source0: %{name}-%{version}.tar.gz Source1001: %{name}.manifest BuildRequires: pkgconfig(icu-uc) -BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(openssl1.1) BuildRequires: pkgconfig(zlib) BuildRequires: pkgconfig(libcares) BuildRequires: pkgconfig(libnghttp2) -- 2.34.1 From 14bcc6b79f4f26ee7821f1809961bddc3a1ae63d Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 9 May 2019 11:27:13 +0900 Subject: [PATCH 05/16] link missed library for DLP Change-Id: If9719a2c13e7d2f37ed1d53b81f070fbfd5bc022 --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 91017a0fb..f09976444 100755 --- a/configure.ac +++ b/configure.ac @@ -3491,6 +3491,7 @@ AC_ARG_ENABLE([dlp], AS_IF([test "x$enable_dlp" = "xyes"], [ CPPFLAGS+=" -DUSE_TIZEN_FEATURE_DLP" + LIBS="-ldl $LIBS" ]) AM_CONDITIONAL(USE_TIZEN_FEATURE_DLP, test "x$enable_dlp" = "xyes") -- 2.34.1 From 3cf00853ec18e74b2fa326583bec82c179b9391a Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 9 May 2019 13:26:42 +0900 Subject: [PATCH 06/16] Revert "link missed library for DLP" This reverts commit 14bcc6b79f4f26ee7821f1809961bddc3a1ae63d. Change-Id: I2fe882d909e8a4d0669ad4a5a63a856ebd0b6d53 --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index f09976444..91017a0fb 100755 --- a/configure.ac +++ b/configure.ac @@ -3491,7 +3491,6 @@ AC_ARG_ENABLE([dlp], AS_IF([test "x$enable_dlp" = "xyes"], [ CPPFLAGS+=" -DUSE_TIZEN_FEATURE_DLP" - LIBS="-ldl $LIBS" ]) AM_CONDITIONAL(USE_TIZEN_FEATURE_DLP, test "x$enable_dlp" = "xyes") -- 2.34.1 From 94481cc16cfc1c454380d2971b2ed728e0e3b95c Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 9 May 2019 11:27:13 +0900 Subject: [PATCH 07/16] link missed library for DLP Change-Id: I77ab3d84ffae5851d9a81a8f834dfce08b34bf6f --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 91017a0fb..f09976444 100755 --- a/configure.ac +++ b/configure.ac @@ -3491,6 +3491,7 @@ AC_ARG_ENABLE([dlp], AS_IF([test "x$enable_dlp" = "xyes"], [ CPPFLAGS+=" -DUSE_TIZEN_FEATURE_DLP" + LIBS="-ldl $LIBS" ]) AM_CONDITIONAL(USE_TIZEN_FEATURE_DLP, test "x$enable_dlp" = "xyes") -- 2.34.1 From dcbf5ac83708a6edb385b9fde2a963d9986f2f77 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 23 Jul 2019 17:51:14 +0900 Subject: [PATCH 08/16] CURL_MAX_INPUT_LENGTH: largest acceptable string input size This limits all accepted input strings passed to libcurl to be less than CURL_MAX_INPUT_LENGTH (8000000) bytes, for these API calls: curl_easy_setopt() and curl_url_set(). The 8000000 number is arbitrary picked and is meant to detect mistakes or abuse, not to limit actual practical use cases. By limiting the acceptable string lengths we also reduce the risk of integer overflows all over. NOTE: This does not apply to `CURLOPT_POSTFIELDS`. Test 1559 verifies. ClosesThis commit closes pull request #3805. #3805 CVE-2019-5435 Change-Id: I0a6d76769e1471352a477a8b1160672757a2de54 --- lib/setopt.c | 7 +++++++ lib/urlapi.c | 8 ++++++++ lib/urldata.h | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/lib/setopt.c b/lib/setopt.c index 22956a20f..06c5f5871 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -60,6 +60,13 @@ CURLcode Curl_setstropt(char **charp, const char *s) if(s) { char *str = strdup(s); + if(str) { + size_t len = strlen(str); + if(len > CURL_MAX_INPUT_LENGTH) { + free(str); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + } if(!str) return CURLE_OUT_OF_MEMORY; diff --git a/lib/urlapi.c b/lib/urlapi.c index c53e52343..f1ef28b0b 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -621,6 +621,10 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned int flags) ************************************************************/ /* allocate scratch area */ urllen = strlen(url); + if(urllen > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + path = u->scratch = malloc(urllen * 2 + 2); if(!path) return CURLUE_OUT_OF_MEMORY; @@ -1249,6 +1253,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, const char *newp = part; size_t nalloc = strlen(part); + if(nalloc > CURL_MAX_INPUT_LENGTH) + /* excessive input length */ + return CURLUE_MALFORMED_INPUT; + if(urlencode) { const char *i; char *o; diff --git a/lib/urldata.h b/lib/urldata.h index 11a6a22c6..5e9b52f29 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -79,6 +79,10 @@ */ #define RESP_TIMEOUT (1800*1000) +/* Max string intput length is a precaution against abuse and to detect junk + input easier and better. */ +#define CURL_MAX_INPUT_LENGTH 8000000 + #include "cookie.h" #include "psl.h" #include "formdata.h" -- 2.34.1 From 22ce8113ef79753e458d7b177317068600ec15c4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 24 Nov 2018 23:20:19 +0100 Subject: [PATCH 09/16] curl_easy_perform: fix timeout handling curl_multi_wait() was erroneously used from within curl_easy_perform(). It could lead to it believing there was no socket to wait for and then instead sleep for a while instead of monitoring the socket and then miss acting on that activity as swiftly as it should (causing an up to 1000 ms delay). Reported-by: Antoni Villalonga Fixes #3305 Clodes #3306 Backported patch details: https://github.com/curl/curl/commit/d04cef9ce1d710902d90b62de01115b9bbe958bf.patch Change-Id: I08d95e996dd9bab5d9fd7c7fe581fdb40c8a0de8 Signed-off-by: Niraj Kumar Goit --- lib/easy.c | 7 ++++--- lib/multi.c | 20 ++++++++++++++++++-- lib/multiif.h | 8 ++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/easy.c b/lib/easy.c index e51cfab19..2612f9590 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -674,12 +674,12 @@ static CURLcode easy_transfer(struct Curl_multi *multi) while(!done && !mcode) { int still_running = 0; - int rc; + bool gotsocket = FALSE; - mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc); + mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket); if(!mcode) { - if(!rc) { + if(!gotsocket) { long sleep_ms; /* If it returns without any filedescriptor instantly, we need to @@ -698,6 +698,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi) /* only read 'still_running' if curl_multi_perform() return OK */ if(!mcode && !still_running) { + int rc; CURLMsg *msg = curl_multi_info_read(multi, &rc); if(msg) { result = msg->data.result; diff --git a/lib/multi.c b/lib/multi.c index 0db2a9730..2c7722a54 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -985,11 +985,12 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi, #define NUM_POLLS_ON_STACK 10 -CURLMcode curl_multi_wait(struct Curl_multi *multi, +CURLMcode Curl_multi_wait(struct Curl_multi *multi, struct curl_waitfd extra_fds[], unsigned int extra_nfds, int timeout_ms, - int *ret) + int *ret, + bool *gotsocket) /* if any socket was checked */ { struct Curl_easy *data; curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; @@ -1003,6 +1004,9 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, int retcode = 0; struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK]; + if(gotsocket) + *gotsocket = FALSE; + if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -1135,9 +1139,21 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi, free(ufds); if(ret) *ret = retcode; + if(gotsocket && (extra_fds || curlfds)) + /* if any socket was checked */ + *gotsocket = TRUE; + return CURLM_OK; } +CURLMcode curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret) +{ + return Curl_multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, NULL); +} /* * Curl_multi_connchanged() is called to tell that there is a connection in * this multi handle that has changed state (pipelining become possible, the diff --git a/lib/multiif.h b/lib/multiif.h index c8fb5ca0d..33dbdddf3 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -97,4 +97,12 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s); CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, struct Curl_easy *data, struct connectdata *conn); + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket); /* if any socket was checked */ + #endif /* HEADER_CURL_MULTIIF_H */ -- 2.34.1 From a90300110f42b1b3091093ec87eef56c9e644c05 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 3 May 2019 22:20:37 +0200 Subject: [PATCH 10/16] tftp: use the current blksize for recvfrom() bug: https://curl.haxx.se/docs/CVE-2019-5436.html Reported-by: l00p3r on hackerone CVE-2019-5436 Backported patch link: https://github.com/curl/curl/commit/2576003415625d7b5f0e390902f8097830b82275.patch Change-Id: Ic6093d1d475ed9ba87e41cff315befdc3aca9c1d Signed-off-by: Nishant Chaprana --- lib/tftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tftp.c b/lib/tftp.c index 5b74e8e08..479e84752 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -1005,7 +1005,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) state->sockfd = state->conn->sock[FIRSTSOCKET]; state->state = TFTP_STATE_START; state->error = TFTP_ERR_NONE; - state->blksize = TFTP_BLKSIZE_DEFAULT; + state->blksize = blksize; state->requested_blksize = blksize; ((struct sockaddr *)&state->local_addr)->sa_family = -- 2.34.1 From a1216fb97bfcc72a902fc8c92b7f9084f5a038da Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Thu, 19 Sep 2019 13:56:58 +0900 Subject: [PATCH 11/16] ftp: Alloc maximum blksize, and use default unless OACK is received Fixes potential buffer overflow from 'recvfrom()', should the server return an OACK without blksize. Bug: https://curl.haxx.se/docs/CVE-2019-5482.html CVE-2019-5482 Change-Id: I6c63f958f4b49aa214ea4adb55c8f85a4b1606cc --- lib/tftp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/tftp.c b/lib/tftp.c index 479e84752..32c6df533 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -969,6 +969,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) { tftp_state_data_t *state; int blksize; + int need_blksize; blksize = TFTP_BLKSIZE_DEFAULT; @@ -983,15 +984,20 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) return CURLE_TFTP_ILLEGAL; } + need_blksize = blksize; + /* default size is the fallback when no OACK is received */ + if(need_blksize < TFTP_BLKSIZE_DEFAULT) + need_blksize = TFTP_BLKSIZE_DEFAULT; + if(!state->rpacket.data) { - state->rpacket.data = calloc(1, blksize + 2 + 2); + state->rpacket.data = calloc(1, need_blksize + 2 + 2); if(!state->rpacket.data) return CURLE_OUT_OF_MEMORY; } if(!state->spacket.data) { - state->spacket.data = calloc(1, blksize + 2 + 2); + state->spacket.data = calloc(1, need_blksize + 2 + 2); if(!state->spacket.data) return CURLE_OUT_OF_MEMORY; @@ -1005,7 +1011,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done) state->sockfd = state->conn->sock[FIRSTSOCKET]; state->state = TFTP_STATE_START; state->error = TFTP_ERR_NONE; - state->blksize = blksize; + state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ state->requested_blksize = blksize; ((struct sockaddr *)&state->local_addr)->sa_family = -- 2.34.1 From a4bb8ac9a00e106b797056bd699547873bd4564b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 3 Sep 2019 22:59:32 +0200 Subject: [PATCH 12/16] security:read_data fix bad realloc() ... that could end up a double-free CVE-2019-5481 Bug: https://curl.haxx.se/docs/CVE-2019-5481.html Change-Id: I4eab9aceba3ad01607eb4f302200e9f949ea4312 --- lib/security.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/security.c b/lib/security.c index 6165d0af0..0b4ad27cf 100644 --- a/lib/security.c +++ b/lib/security.c @@ -193,7 +193,6 @@ static CURLcode read_data(struct connectdata *conn, struct krb5buffer *buf) { int len; - void *tmp = NULL; CURLcode result; result = socket_read(fd, &len, sizeof(len)); @@ -203,12 +202,11 @@ static CURLcode read_data(struct connectdata *conn, if(len) { /* only realloc if there was a length */ len = ntohl(len); - tmp = Curl_saferealloc(buf->data, len); + buf->data = Curl_saferealloc(buf->data, len); } - if(tmp == NULL) + if(!len || !buf->data) return CURLE_OUT_OF_MEMORY; - buf->data = tmp; result = socket_read(fd, buf->data, len); if(result) return result; -- 2.34.1 From 4f3fa80d379be530352347c7bd7fb87de4e4669f Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 24 Sep 2019 15:25:37 +0900 Subject: [PATCH 13/16] http2: Stop drain from being permanently set on Various functions called within Curl_http2_done() can have the side-effect of setting the Easy connection into drain mode (by calling drain_this()). However, the last time we unset this for a transfer (by calling drained_transfer()) is at the beginning of Curl_http2_done(). If the Curl_easy is reused for another transfer, it is then stuck in drain mode permanently, which in practice makes it unable to write any data in the new transfer. This fix moves the last call to drained_transfer() to later in Curl_http2_done(), after the functions that could potentially call for a drain. Fixes #3966 Reported-by: Josie-H Change-Id: I83ee02bf9017c9aa3d27d50580a0f89b8ec1d05d --- lib/http2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/http2.c b/lib/http2.c index 0c5f6db0b..0c8b59d1a 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -1163,9 +1163,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature) if(!httpc->h2) /* not HTTP/2 ? */ return; - if(data->state.drain) - drained_transfer(data, httpc); - if(premature) { /* RST_STREAM */ if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, @@ -1177,6 +1174,10 @@ void Curl_http2_done(struct connectdata *conn, bool premature) httpc->pause_stream_id = 0; } } + + if(data->state.drain) + drained_transfer(data, httpc); + /* -1 means unassigned and 0 means cleared */ if(http->stream_id > 0) { int rv = nghttp2_session_set_stream_user_data(httpc->h2, -- 2.34.1 From d0228317834e191148159cf7139ae175e782154f Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Tue, 8 Oct 2019 15:29:30 +0900 Subject: [PATCH 14/16] Revert "Use openssl-1.1" This reverts commit 6b333876d2db240bd01e0dcec950b2d12dc8eae5. Change-Id: Ia687599375fb2953e9df43f7195877726c5ffa29 --- packaging/curl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/curl.spec b/packaging/curl.spec index f0572490c..8e4f44789 100644 --- a/packaging/curl.spec +++ b/packaging/curl.spec @@ -10,7 +10,7 @@ Source0: %{name}-%{version}.tar.gz Source1001: %{name}.manifest BuildRequires: pkgconfig(icu-uc) -BuildRequires: pkgconfig(openssl1.1) +BuildRequires: pkgconfig(openssl) BuildRequires: pkgconfig(zlib) BuildRequires: pkgconfig(libcares) BuildRequires: pkgconfig(libnghttp2) -- 2.34.1 From bfd1c3da373e54e8ee7adecaa5cbe8b70686f727 Mon Sep 17 00:00:00 2001 From: Seonah Moon Date: Wed, 30 Oct 2019 11:34:31 +0900 Subject: [PATCH 15/16] Curl_fillreadbuffer: avoid double-free trailer buf on error Backported Patch link: https://github.com/curl/curl/pull/4307 Change-Id: I5b695b661cf946b74e065d1a65697e74d7ef8af6 --- lib/http.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/http.c b/lib/http.c index 46ac15a6e..1be9c0f44 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1095,10 +1095,14 @@ Curl_send_buffer *Curl_add_buffer_init(void) */ void Curl_add_buffer_free(Curl_send_buffer **inp) { - Curl_send_buffer *in = *inp; - if(in) /* deal with NULL input */ + Curl_send_buffer *in; + if(!inp) + return; + in = *inp; + if(in) { /* deal with NULL input */ free(in->buffer); - free(in); + free(in); + } *inp = NULL; } -- 2.34.1 From 8dfb92873af9de5d883e191e0097be32c78a7d0f Mon Sep 17 00:00:00 2001 From: Niraj Kumar Goit Date: Mon, 2 Dec 2019 15:34:23 +0530 Subject: [PATCH 16/16] ares: remove fd from multi fd set when ares is about to close the fd When using c-ares for asyn dns, the dns socket fd was silently closed by c-ares without curl being aware. curl would then 'realize' the fd has been removed at next call of Curl_resolver_getsock, and only then notify the CURLMOPT_SOCKETFUNCTION to remove fd from its poll set with CURL_POLL_REMOVE. At this point the fd is already closed. By using ares socket state callback (ARES_OPT_SOCK_STATE_CB), this patch allows curl to be notified that the fd is not longer needed for neither for write nor read. At this point by calling Curl_multi_closed we are able to notify multi with CURL_POLL_REMOVE before the fd is actually closed by ares. In asyn-ares.c Curl_resolver_duphandle we can't use ares_dup anymore since it does not allow passing a different sock_state_cb_data Backported patch details: https://github.com/curl/curl/commit/6765e6d9e6a32bb4fc666d744cb57e2d55d4e13b Change-Id: I62b2d244cb0f38a4c4a76ad804c7fd69f9222484 Signed-off-by: Niraj Kumar Goit --- lib/asyn-ares.c | 37 +++++++++++++++++++++++-------------- lib/asyn-thread.c | 7 ++++--- lib/asyn.h | 9 +++++---- lib/connect.c | 4 ++-- lib/easy.c | 3 ++- lib/multi.c | 8 ++++---- lib/multiif.h | 2 +- lib/url.c | 2 +- 8 files changed, 42 insertions(+), 30 deletions(-) diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index c3928082b..b65ffde39 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -124,6 +124,17 @@ void Curl_resolver_global_cleanup(void) #endif } + +static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd, + int readable, int writable) +{ + struct Curl_easy *easy = data; + if(!readable && !writable) { + DEBUGASSERT(easy); + Curl_multi_closed(easy, socket_fd); + } +} + /* * Curl_resolver_init() * @@ -131,21 +142,16 @@ void Curl_resolver_global_cleanup(void) * URL-state specific environment ('resolver' member of the UrlState * structure). Fills the passed pointer by the initialized ares_channel. */ -CURLcode Curl_resolver_init(void **resolver) +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) { #ifndef TIZEN_TV_EXT int status = ares_init((ares_channel*)resolver); #else int status; struct ares_options options; - int optmask = 0; - - options.timeout = DEFAULT_TIMEOUT; - optmask |= ARES_OPT_TIMEOUTMS; - - options.tries = DEFAULT_TRIES; - optmask |= ARES_OPT_TRIES; - + int optmask = ARES_OPT_SOCK_STATE_CB; + options.sock_state_cb = Curl_ares_sock_state_cb; + options.sock_state_cb_data = easy; status = ares_init_options((ares_channel*)resolver, &options, optmask); #endif if(status != ARES_SUCCESS) { @@ -178,12 +184,15 @@ void Curl_resolver_cleanup(void *resolver) * environment ('resolver' member of the UrlState structure). Duplicates the * 'from' ares channel and passes the resulting channel to the 'to' pointer. */ -int Curl_resolver_duphandle(void **to, void *from) +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) { - /* Clone the ares channel for the new handle */ - if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from)) - return CURLE_FAILED_INIT; - return CURLE_OK; + (void)from; + /* + * it would be better to call ares_dup instead, but right now + * it is not possible to set 'sock_state_cb_data' outside of + * ares_init_options + */ + return Curl_resolver_init(easy, to); } static void destroy_async_data(struct Curl_async *async); diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 2a59294e5..4c8f88b14 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -108,8 +108,9 @@ void Curl_resolver_global_cleanup(void) * URL-state specific environment ('resolver' member of the UrlState * structure). */ -CURLcode Curl_resolver_init(void **resolver) +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver) { + (void)easy; *resolver = calloc(1, sizeof(struct resdata)); if(!*resolver) return CURLE_OUT_OF_MEMORY; @@ -132,10 +133,10 @@ void Curl_resolver_cleanup(void *resolver) * Called from curl_easy_duphandle() to duplicate resolver URL state-specific * environment ('resolver' member of the UrlState structure). */ -int Curl_resolver_duphandle(void **to, void *from) +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from) { (void)from; - return Curl_resolver_init(to); + return Curl_resolver_init(easy, to); } static void destroy_async_data(struct Curl_async *); diff --git a/lib/asyn.h b/lib/asyn.h index 3adc3664a..43625bc3b 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -60,7 +60,7 @@ void Curl_resolver_global_cleanup(void); * Returning anything else than CURLE_OK fails curl_easy_init() with the * correspondent code. */ -CURLcode Curl_resolver_init(void **resolver); +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver); /* * Curl_resolver_cleanup() @@ -79,7 +79,8 @@ void Curl_resolver_cleanup(void *resolver); * pointer. Returning anything else than CURLE_OK causes failed * curl_easy_duphandle() call. */ -int Curl_resolver_duphandle(void **to, void *from); +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, + void *from); /* * Curl_resolver_cancel(). @@ -150,8 +151,8 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST #define Curl_resolver_getsock(x,y,z) 0 -#define Curl_resolver_duphandle(x,y) CURLE_OK -#define Curl_resolver_init(x) CURLE_OK +#define Curl_resolver_duphandle(x,y,z) CURLE_OK +#define Curl_resolver_init(x,y) CURLE_OK #define Curl_resolver_global_init() CURLE_OK #define Curl_resolver_global_cleanup() Curl_nop_stmt #define Curl_resolver_cleanup(x) Curl_nop_stmt diff --git a/lib/connect.c b/lib/connect.c index 41f220268..18645b9b7 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -1314,7 +1314,7 @@ int Curl_closesocket(struct connectdata *conn, conn->sock_accepted[SECONDARYSOCKET] = FALSE; else { int rc; - Curl_multi_closed(conn, sock); + Curl_multi_closed(conn->data, sock); Curl_set_in_callback(conn->data, true); rc = conn->fclosesocket(conn->closesocket_client, sock); Curl_set_in_callback(conn->data, false); @@ -1324,7 +1324,7 @@ int Curl_closesocket(struct connectdata *conn, if(conn) /* tell the multi-socket code about this */ - Curl_multi_closed(conn, sock); + Curl_multi_closed(conn->data, sock); sclose(sock); diff --git a/lib/easy.c b/lib/easy.c index 2612f9590..4132decc8 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -977,7 +977,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) } /* Clone the resolver handle, if present, for the new handle */ - if(Curl_resolver_duphandle(&outcurl->state.resolver, + if(Curl_resolver_duphandle(outcurl, + &outcurl->state.resolver, data->state.resolver)) goto fail; diff --git a/lib/multi.c b/lib/multi.c index 2c7722a54..632250e26 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -2482,11 +2482,11 @@ void Curl_updatesocket(struct Curl_easy *data) * socket again and it gets the same file descriptor number. */ -void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s) { - if(conn->data) { + if(data) { /* if there's still an easy handle associated with this connection */ - struct Curl_multi *multi = conn->data->multi; + struct Curl_multi *multi = data->multi; if(multi) { /* this is set if this connection is part of a handle that is added to a multi handle, and only then this is necessary */ @@ -2494,7 +2494,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) if(entry) { if(multi->socket_cb) - multi->socket_cb(conn->data, s, CURL_POLL_REMOVE, + multi->socket_cb(data, s, CURL_POLL_REMOVE, multi->socket_userp, entry->socketp); diff --git a/lib/multiif.h b/lib/multiif.h index 33dbdddf3..e44646bf9 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -89,7 +89,7 @@ void Curl_multi_connchanged(struct Curl_multi *multi); * socket again and it gets the same file descriptor number. */ -void Curl_multi_closed(struct connectdata *conn, curl_socket_t s); +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s); /* * Add a handle and move it into PERFORM state at once. For pushed streams. diff --git a/lib/url.c b/lib/url.c index bf1eb63f8..73f3eb3f5 100644 --- a/lib/url.c +++ b/lib/url.c @@ -576,7 +576,7 @@ CURLcode Curl_open(struct Curl_easy **curl) data->magic = CURLEASY_MAGIC_NUMBER; - result = Curl_resolver_init(&data->state.resolver); + result = Curl_resolver_init(data, &data->state.resolver); if(result) { DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); free(data); -- 2.34.1