1 /* 2 * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "internal/common.h" 11 #include "internal/quic_ssl.h" 12 #include "internal/quic_reactor_wait_ctx.h" 13 #include <openssl/ssl.h> 14 #include <openssl/err.h> 15 #include "../ssl_local.h" 16 #include "poll_builder.h" 17 18 #if defined(_AIX) 19 /* 20 * Some versions of AIX define macros for events and revents for use when 21 * accessing pollfd structures (see Github issue #24236). That interferes 22 * with our use of these names here. We simply undef them. 23 */ 24 #undef revents 25 #undef events 26 #endif 27 28 #define ITEM_N(items, stride, n) \ 29 (*(SSL_POLL_ITEM *)((char *)(items) + (n) * (stride))) 30 31 #define FAIL_FROM(n) \ 32 do { \ 33 size_t j; \ 34 \ 35 for (j = (n); j < num_items; ++j) \ 36 ITEM_N(items, stride, j).revents = 0; \ 37 \ 38 ok = 0; \ 39 goto out; \ 40 } while (0) 41 42 #define FAIL_ITEM(idx) \ 43 do { \ 44 size_t idx_ = (idx); \ 45 \ 46 ITEM_N(items, stride, idx_).revents = SSL_POLL_EVENT_F; \ 47 ++result_count; \ 48 FAIL_FROM(idx_ + 1); \ 49 } while (0) 50 51 #ifndef OPENSSL_NO_QUIC 52 static int poll_translate_ssl_quic(SSL *ssl, 53 QUIC_REACTOR_WAIT_CTX *wctx, 54 RIO_POLL_BUILDER *rpb, 55 uint64_t events, 56 int *abort_blocking) 57 { 58 BIO_POLL_DESCRIPTOR rd, wd; 59 int fd1 = -1, fd2 = -1, fd_nfy = -1; 60 int fd1_r = 0, fd1_w = 0, fd2_w = 0; 61 62 if (SSL_net_read_desired(ssl)) { 63 if (!SSL_get_rpoll_descriptor(ssl, &rd)) { 64 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 65 "SSL_poll requires the network BIOs underlying " 66 "a QUIC SSL object provide poll descriptors"); 67 return 0; 68 } 69 70 if (rd.type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) { 71 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 72 "SSL_poll requires the poll descriptors of the " 73 "network BIOs underlying a QUIC SSL object be " 74 "of socket type"); 75 return 0; 76 } 77 78 fd1 = rd.value.fd; 79 fd1_r = 1; 80 } 81 82 if (SSL_net_write_desired(ssl)) { 83 if (!SSL_get_wpoll_descriptor(ssl, &wd)) { 84 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 85 "SSL_poll requires the network BIOs underlying " 86 "a QUIC SSL object provide poll descriptors"); 87 return 0; 88 } 89 90 if (wd.type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) { 91 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 92 "SSL_poll requires the poll descriptors of the " 93 "network BIOs underlying a QUIC SSL object be " 94 "of socket type"); 95 return 0; 96 } 97 98 fd2 = wd.value.fd; 99 fd2_w = 1; 100 } 101 102 if (fd2 == fd1) { 103 fd2 = -1; 104 fd1_w = fd2_w; 105 } 106 107 if (fd1 != -1) 108 if (!ossl_rio_poll_builder_add_fd(rpb, fd1, fd1_r, fd1_w)) 109 return 0; 110 111 if (fd2 != -1 && fd2_w) 112 if (!ossl_rio_poll_builder_add_fd(rpb, fd2, /*r = */ 0, fd2_w)) 113 return 0; 114 115 /* 116 * Add the notifier FD for the QUIC domain this SSL object is a part of (if 117 * there is one). This ensures we get woken up if another thread calls into 118 * that QUIC domain and some readiness event relevant to the SSL_poll call 119 * on this thread arises without the underlying network socket ever becoming 120 * readable. 121 */ 122 fd_nfy = ossl_quic_get_notifier_fd(ssl); 123 if (fd_nfy != -1) { 124 uint64_t revents = 0; 125 126 if (!ossl_rio_poll_builder_add_fd(rpb, fd_nfy, /*r = */ 1, /*w = */ 0)) 127 return 0; 128 129 /* Tell QUIC domain we need to receive notifications. */ 130 ossl_quic_enter_blocking_section(ssl, wctx); 131 132 /* 133 * Only after the above call returns is it guaranteed that any readiness 134 * events will cause the above notifier to become readable. Therefore, 135 * it is possible the object became ready after our initial 136 * poll_readout() call (before we determined that nothing was ready and 137 * we needed to block). We now need to do another readout, in which case 138 * blocking is to be aborted. 139 */ 140 if (!ossl_quic_conn_poll_events(ssl, events, /*do_tick = */ 0, &revents)) { 141 ossl_quic_leave_blocking_section(ssl, wctx); 142 return 0; 143 } 144 145 if (revents != 0) { 146 ossl_quic_leave_blocking_section(ssl, wctx); 147 *abort_blocking = 1; 148 return 1; 149 } 150 } 151 152 return 1; 153 } 154 155 static void postpoll_translation_cleanup_ssl_quic(SSL *ssl, 156 QUIC_REACTOR_WAIT_CTX *wctx) 157 { 158 if (ossl_quic_get_notifier_fd(ssl) != -1) 159 ossl_quic_leave_blocking_section(ssl, wctx); 160 } 161 162 static void postpoll_translation_cleanup(SSL_POLL_ITEM *items, 163 size_t num_items, 164 size_t stride, 165 QUIC_REACTOR_WAIT_CTX *wctx) 166 { 167 SSL_POLL_ITEM *item; 168 SSL *ssl; 169 size_t i; 170 171 for (i = 0; i < num_items; ++i) { 172 item = &ITEM_N(items, stride, i); 173 174 switch (item->desc.type) { 175 case BIO_POLL_DESCRIPTOR_TYPE_SSL: 176 ssl = item->desc.value.ssl; 177 if (ssl == NULL) 178 break; 179 180 switch (ssl->type) { 181 #ifndef OPENSSL_NO_QUIC 182 case SSL_TYPE_QUIC_LISTENER: 183 case SSL_TYPE_QUIC_CONNECTION: 184 case SSL_TYPE_QUIC_XSO: 185 postpoll_translation_cleanup_ssl_quic(ssl, wctx); 186 break; 187 #endif 188 default: 189 break; 190 } 191 break; 192 default: 193 break; 194 } 195 } 196 } 197 198 static int poll_translate(SSL_POLL_ITEM *items, 199 size_t num_items, 200 size_t stride, 201 QUIC_REACTOR_WAIT_CTX *wctx, 202 RIO_POLL_BUILDER *rpb, 203 OSSL_TIME *p_earliest_wakeup_deadline, 204 int *abort_blocking, 205 size_t *p_result_count) 206 { 207 int ok = 1; 208 SSL_POLL_ITEM *item; 209 size_t result_count = 0; 210 SSL *ssl; 211 OSSL_TIME earliest_wakeup_deadline = ossl_time_infinite(); 212 struct timeval timeout; 213 int is_infinite = 0; 214 size_t i; 215 216 for (i = 0; i < num_items; ++i) { 217 item = &ITEM_N(items, stride, i); 218 219 switch (item->desc.type) { 220 case BIO_POLL_DESCRIPTOR_TYPE_SSL: 221 ssl = item->desc.value.ssl; 222 if (ssl == NULL) 223 /* NULL items are no-ops and have revents reported as 0 */ 224 break; 225 226 switch (ssl->type) { 227 #ifndef OPENSSL_NO_QUIC 228 case SSL_TYPE_QUIC_LISTENER: 229 case SSL_TYPE_QUIC_CONNECTION: 230 case SSL_TYPE_QUIC_XSO: 231 if (!poll_translate_ssl_quic(ssl, wctx, rpb, item->events, 232 abort_blocking)) 233 FAIL_ITEM(i); 234 235 if (*abort_blocking) 236 return 1; 237 238 if (!SSL_get_event_timeout(ssl, &timeout, &is_infinite)) 239 FAIL_ITEM(i++); /* need to clean up this item too */ 240 241 if (!is_infinite) 242 earliest_wakeup_deadline 243 = ossl_time_min(earliest_wakeup_deadline, 244 ossl_time_add(ossl_time_now(), 245 ossl_time_from_timeval(timeout))); 246 247 break; 248 #endif 249 250 default: 251 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 252 "SSL_poll currently only supports QUIC SSL " 253 "objects"); 254 FAIL_ITEM(i); 255 } 256 break; 257 258 case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD: 259 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 260 "SSL_poll currently does not support polling " 261 "sockets"); 262 FAIL_ITEM(i); 263 264 default: 265 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 266 "SSL_poll does not support unknown poll descriptor " 267 "type %d", 268 item->desc.type); 269 FAIL_ITEM(i); 270 } 271 } 272 273 out: 274 if (!ok) 275 postpoll_translation_cleanup(items, i, stride, wctx); 276 277 *p_earliest_wakeup_deadline = earliest_wakeup_deadline; 278 *p_result_count = result_count; 279 return ok; 280 } 281 282 static int poll_block(SSL_POLL_ITEM *items, 283 size_t num_items, 284 size_t stride, 285 OSSL_TIME user_deadline, 286 size_t *p_result_count) 287 { 288 int ok = 0, abort_blocking = 0; 289 RIO_POLL_BUILDER rpb; 290 QUIC_REACTOR_WAIT_CTX wctx; 291 OSSL_TIME earliest_wakeup_deadline; 292 293 /* 294 * Blocking is somewhat involved and involves the following steps: 295 * 296 * - Translation, in which the various logical items (SSL objects, etc.) to 297 * be polled are translated into items an OS polling API understands. 298 * 299 * - Synchronisation bookkeeping. This ensures that we can be woken up 300 * not just by readiness of any underlying file descriptor distilled from 301 * the provided items but also by other threads, which might do work 302 * on a relevant QUIC object to cause the object to be ready without the 303 * underlying file descriptor ever becoming ready from our perspective. 304 * 305 * - The blocking call to the OS polling API. 306 * 307 * - Currently we do not do reverse translation but simply call 308 * poll_readout() again to read out all readiness state for all 309 * descriptors which the user passed. 310 * 311 * TODO(QUIC POLLING): In the future we will do reverse translation here 312 * also to facilitate a more efficient readout. 313 */ 314 ossl_quic_reactor_wait_ctx_init(&wctx); 315 ossl_rio_poll_builder_init(&rpb); 316 317 if (!poll_translate(items, num_items, stride, &wctx, &rpb, 318 &earliest_wakeup_deadline, 319 &abort_blocking, 320 p_result_count)) 321 goto out; 322 323 if (abort_blocking) 324 goto out; 325 326 earliest_wakeup_deadline = ossl_time_min(earliest_wakeup_deadline, 327 user_deadline); 328 329 ok = ossl_rio_poll_builder_poll(&rpb, earliest_wakeup_deadline); 330 331 postpoll_translation_cleanup(items, num_items, stride, &wctx); 332 333 out: 334 ossl_rio_poll_builder_cleanup(&rpb); 335 ossl_quic_reactor_wait_ctx_cleanup(&wctx); 336 return ok; 337 } 338 #endif 339 340 static int poll_readout(SSL_POLL_ITEM *items, 341 size_t num_items, 342 size_t stride, 343 int do_tick, 344 size_t *p_result_count) 345 { 346 int ok = 1; 347 size_t i, result_count = 0; 348 SSL_POLL_ITEM *item; 349 SSL *ssl; 350 #ifndef OPENSSL_NO_QUIC 351 uint64_t events; 352 #endif 353 uint64_t revents; 354 355 for (i = 0; i < num_items; ++i) { 356 item = &ITEM_N(items, stride, i); 357 #ifndef OPENSSL_NO_QUIC 358 events = item->events; 359 #endif 360 revents = 0; 361 362 switch (item->desc.type) { 363 case BIO_POLL_DESCRIPTOR_TYPE_SSL: 364 ssl = item->desc.value.ssl; 365 if (ssl == NULL) 366 /* NULL items are no-ops and have revents reported as 0 */ 367 break; 368 369 switch (ssl->type) { 370 #ifndef OPENSSL_NO_QUIC 371 case SSL_TYPE_QUIC_LISTENER: 372 case SSL_TYPE_QUIC_CONNECTION: 373 case SSL_TYPE_QUIC_XSO: 374 if (!ossl_quic_conn_poll_events(ssl, events, do_tick, &revents)) 375 /* above call raises ERR */ 376 FAIL_ITEM(i); 377 378 if (revents != 0) 379 ++result_count; 380 381 break; 382 #endif 383 384 default: 385 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 386 "SSL_poll currently only supports QUIC SSL " 387 "objects"); 388 FAIL_ITEM(i); 389 } 390 break; 391 case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD: 392 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 393 "SSL_poll currently does not support polling " 394 "sockets"); 395 FAIL_ITEM(i); 396 default: 397 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 398 "SSL_poll does not support unknown poll descriptor " 399 "type %d", 400 item->desc.type); 401 FAIL_ITEM(i); 402 } 403 404 item->revents = revents; 405 } 406 407 out: 408 if (p_result_count != NULL) 409 *p_result_count = result_count; 410 411 return ok; 412 } 413 414 int SSL_poll(SSL_POLL_ITEM *items, 415 size_t num_items, 416 size_t stride, 417 const struct timeval *timeout, 418 uint64_t flags, 419 size_t *p_result_count) 420 { 421 int ok = 1; 422 size_t result_count = 0; 423 ossl_unused int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0); 424 OSSL_TIME deadline; 425 426 /* Trivial case. */ 427 if (num_items == 0) { 428 if (timeout == NULL) 429 goto out; 430 OSSL_sleep(ossl_time2ms(ossl_time_from_timeval(*timeout))); 431 goto out; 432 } 433 434 /* Convert timeout to deadline. */ 435 if (timeout == NULL) 436 deadline = ossl_time_infinite(); 437 else if (timeout->tv_sec == 0 && timeout->tv_usec == 0) 438 deadline = ossl_time_zero(); 439 else 440 deadline = ossl_time_add(ossl_time_now(), 441 ossl_time_from_timeval(*timeout)); 442 443 /* Loop until we have something to report. */ 444 for (;;) { 445 /* Readout phase - poll current state of each item. */ 446 if (!poll_readout(items, num_items, stride, do_tick, &result_count)) { 447 ok = 0; 448 goto out; 449 } 450 451 /* 452 * If we got anything, or we are in immediate mode (zero timeout), or 453 * the deadline has expired, we're done. 454 */ 455 if (result_count > 0 456 || ossl_time_is_zero(deadline) /* (avoids now call) */ 457 || ossl_time_compare(ossl_time_now(), deadline) >= 0) 458 goto out; 459 460 /* 461 * Block until something is ready. Ignore NO_HANDLE_EVENTS from this 462 * point onwards. 463 */ 464 do_tick = 1; 465 #ifndef OPENSSL_NO_QUIC 466 if (!poll_block(items, num_items, stride, deadline, &result_count)) { 467 ok = 0; 468 goto out; 469 } 470 #endif 471 } 472 473 /* TODO(QUIC POLLING): Support for polling FDs */ 474 475 out: 476 if (p_result_count != NULL) 477 *p_result_count = result_count; 478 479 return ok; 480 } 481