[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 91/97] curl: Handle success in multi_check_completion
From: |
Michael Roth |
Subject: |
[PATCH 91/97] curl: Handle success in multi_check_completion |
Date: |
Tue, 1 Oct 2019 18:46:10 -0500 |
From: Max Reitz <address@hidden>
Background: As of cURL 7.59.0, it verifies that several functions are
not called from within a callback. Among these functions is
curl_multi_add_handle().
curl_read_cb() is a callback from cURL and not a coroutine. Waking up
acb->co will lead to entering it then and there, which means the current
request will settle and the caller (if it runs in the same coroutine)
may then issue the next request. In such a case, we will enter
curl_setup_preadv() effectively from within curl_read_cb().
Calling curl_multi_add_handle() will then fail and the new request will
not be processed.
Fix this by not letting curl_read_cb() wake up acb->co. Instead, leave
the whole business of settling the AIOCB objects to
curl_multi_check_completion() (which is called from our timer callback
and our FD handler, so not from any cURL callbacks).
Reported-by: Natalie Gavrielov <address@hidden>
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193
Cc: address@hidden
Signed-off-by: Max Reitz <address@hidden>
Message-id: address@hidden
Reviewed-by: John Snow <address@hidden>
Reviewed-by: Maxim Levitsky <address@hidden>
Signed-off-by: Max Reitz <address@hidden>
(cherry picked from commit bfb23b480a49114315877aacf700b49453e0f9d9)
Signed-off-by: Michael Roth <address@hidden>
---
block/curl.c | 69 ++++++++++++++++++++++------------------------------
1 file changed, 29 insertions(+), 40 deletions(-)
diff --git a/block/curl.c b/block/curl.c
index de0cebd361..af40203711 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -228,7 +228,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t
nmemb, void *opaque)
{
CURLState *s = ((CURLState*)opaque);
size_t realsize = size * nmemb;
- int i;
trace_curl_read_cb(realsize);
@@ -244,32 +243,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t
nmemb, void *opaque)
memcpy(s->orig_buf + s->buf_off, ptr, realsize);
s->buf_off += realsize;
- for(i=0; i<CURL_NUM_ACB; i++) {
- CURLAIOCB *acb = s->acb[i];
-
- if (!acb)
- continue;
-
- if ((s->buf_off >= acb->end)) {
- size_t request_length = acb->bytes;
-
- qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
- acb->end - acb->start);
-
- if (acb->end - acb->start < request_length) {
- size_t offset = acb->end - acb->start;
- qemu_iovec_memset(acb->qiov, offset, 0,
- request_length - offset);
- }
-
- acb->ret = 0;
- s->acb[i] = NULL;
- qemu_mutex_unlock(&s->s->mutex);
- aio_co_wake(acb->co);
- qemu_mutex_lock(&s->s->mutex);
- }
- }
-
read_end:
/* curl will error out if we do not return this value */
return size * nmemb;
@@ -350,13 +323,14 @@ static void curl_multi_check_completion(BDRVCURLState *s)
break;
if (msg->msg == CURLMSG_DONE) {
+ int i;
CURLState *state = NULL;
+ bool error = msg->data.result != CURLE_OK;
+
curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
(char **)&state);
- /* ACBs for successful messages get completed in curl_read_cb */
- if (msg->data.result != CURLE_OK) {
- int i;
+ if (error) {
static int errcount = 100;
/* Don't lose the original error message from curl, since
@@ -368,20 +342,35 @@ static void curl_multi_check_completion(BDRVCURLState *s)
error_report("curl: further errors suppressed");
}
}
+ }
- for (i = 0; i < CURL_NUM_ACB; i++) {
- CURLAIOCB *acb = state->acb[i];
+ for (i = 0; i < CURL_NUM_ACB; i++) {
+ CURLAIOCB *acb = state->acb[i];
- if (acb == NULL) {
- continue;
- }
+ if (acb == NULL) {
+ continue;
+ }
+
+ if (!error) {
+ /* Assert that we have read all data */
+ assert(state->buf_off >= acb->end);
+
+ qemu_iovec_from_buf(acb->qiov, 0,
+ state->orig_buf + acb->start,
+ acb->end - acb->start);
- acb->ret = -EIO;
- state->acb[i] = NULL;
- qemu_mutex_unlock(&s->mutex);
- aio_co_wake(acb->co);
- qemu_mutex_lock(&s->mutex);
+ if (acb->end - acb->start < acb->bytes) {
+ size_t offset = acb->end - acb->start;
+ qemu_iovec_memset(acb->qiov, offset, 0,
+ acb->bytes - offset);
+ }
}
+
+ acb->ret = error ? -EIO : 0;
+ state->acb[i] = NULL;
+ qemu_mutex_unlock(&s->mutex);
+ aio_co_wake(acb->co);
+ qemu_mutex_lock(&s->mutex);
}
curl_clean_state(state);
--
2.17.1
- [PATCH 93/97] slirp: Fix heap overflow in ip_reass on big packet input, (continued)
- [PATCH 93/97] slirp: Fix heap overflow in ip_reass on big packet input, Michael Roth, 2019/10/01
- [PATCH 95/97] s390: PCI: fix IOMMU region init, Michael Roth, 2019/10/01
- [PATCH 63/97] backup: Copy only dirty areas, Michael Roth, 2019/10/01
- [PATCH 08/97] Makefile: add nit-picky mode to sphinx-build, Michael Roth, 2019/10/01
- [PATCH 97/97] scsi: lsi: exit infinite loop while executing script (CVE-2019-12068), Michael Roth, 2019/10/01
- [PATCH 74/97] xen-bus: Fix backend state transition on device reset, Michael Roth, 2019/10/01
- [PATCH 75/97] pr-manager: Fix invalid g_free() crash bug, Michael Roth, 2019/10/01
- [PATCH 94/97] slirp: ip_reass: Fix use after free, Michael Roth, 2019/10/01
- [PATCH 09/97] docs/interop/bitmaps: rewrite and modernize doc, Michael Roth, 2019/10/01
- [PATCH 23/97] iotests: add iotest 256 for testing blockdev-backup across iothread contexts, Michael Roth, 2019/10/01
- [PATCH 91/97] curl: Handle success in multi_check_completion,
Michael Roth <=
- [PATCH 19/97] iotests.py: do not use infinite waits, Michael Roth, 2019/10/01
- Re: [PATCH 00/97] Patch Round-up for stable 4.0.1, freeze on 2019-10-10, Thomas Huth, 2019/10/02
- Re: [PATCH 00/97] Patch Round-up for stable 4.0.1, freeze on 2019-10-10, Philippe Mathieu-Daudé, 2019/10/03
- Re: [PATCH 00/97] Patch Round-up for stable 4.0.1, freeze on 2019-10-10, Alexandr Iarygin, 2019/10/07
- Re: [PATCH 00/97] Patch Round-up for stable 4.0.1, freeze on 2019-10-10, Philippe Mathieu-Daudé, 2019/10/08
- Re: [PATCH 00/97] Patch Round-up for stable 4.0.1, freeze on 2019-10-10, Anthony PERARD, 2019/10/11