From: Matt Caswell Date: Thu, 25 Jun 2026 16:15:16 +0000 (+0100) Subject: SSL_poll: fix abort_blocking mishandling in poll_translate()/poll_block() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d6ca7796bf66f65d0c69cb0c0806ed38ce3f3105;p=thirdparty%2Fopenssl.git SSL_poll: fix abort_blocking mishandling in poll_translate()/poll_block() When SSL_poll() has to block, poll_translate() registers each item's QUIC connection for cross-thread notification one item at a time. If an item turns out to already be ready right as it is being registered, translation sets abort_blocking and is meant to bail out so the caller retries the readout instead of actually blocking. Two bugs in that abort path: - poll_translate() returned immediately on abort_blocking without calling postpoll_translation_cleanup() for any earlier items that had already had their blocking section entered. Those items' enter/leave calls were left unbalanced, leaking into the QUIC reactor's blocking-waiter count. Fixed by routing through the existing "out" cleanup label, mirroring what the FAIL_ITEM()/error path already does for items 0..i-1. - poll_block() initializes ok = 0 and only ever sets it on the actual poll() success path. The abort_blocking branch jumped straight to "out" without setting ok, so SSL_poll() reported failure even though nothing actually went wrong; the caller's retry loop never got a chance to pick up the now-ready item. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Saša Nedvědický Reviewed-by: Paul Yang MergeDate: Wed Jul 29 07:20:31 2026 (Merged from https://github.com/openssl/openssl/pull/31743) --- diff --git a/ssl/rio/poll_immediate.c b/ssl/rio/poll_immediate.c index 24b82f3a6a4..edb39b2a6c1 100644 --- a/ssl/rio/poll_immediate.c +++ b/ssl/rio/poll_immediate.c @@ -233,7 +233,7 @@ static int poll_translate(SSL_POLL_ITEM *items, FAIL_ITEM(i); if (*abort_blocking) - return 1; + goto out; if (!SSL_get_event_timeout(ssl, &timeout, &is_infinite)) FAIL_ITEM(i++); /* need to clean up this item too */ @@ -271,7 +271,12 @@ static int poll_translate(SSL_POLL_ITEM *items, } out: - if (!ok) + /* + * On abort_blocking, the item which triggered the abort has already + * balanced its own enter/leave of the blocking section (see + * poll_translate_ssl_quic()); only items 0..i-1 still need cleanup here. + */ + if (!ok || *abort_blocking) postpoll_translation_cleanup(items, i, stride, wctx); *p_earliest_wakeup_deadline = earliest_wakeup_deadline; @@ -320,8 +325,15 @@ static int poll_block(SSL_POLL_ITEM *items, p_result_count)) goto out; - if (abort_blocking) + if (abort_blocking) { + /* + * Nothing actually failed; we just shouldn't block because an item + * may have become ready while we were setting up. The caller's + * retry loop will call poll_readout() again to pick this up. + */ + ok = 1; goto out; + } earliest_wakeup_deadline = ossl_time_min(earliest_wakeup_deadline, user_deadline);