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", item->desc.type); 268 FAIL_ITEM(i); 269 } 270 } 271 272 out: 273 if (!ok) 274 postpoll_translation_cleanup(items, i, stride, wctx); 275 276 *p_earliest_wakeup_deadline = earliest_wakeup_deadline; 277 *p_result_count = result_count; 278 return ok; 279 } 280 281 static int poll_block(SSL_POLL_ITEM *items, 282 size_t num_items, 283 size_t stride, 284 OSSL_TIME user_deadline, 285 size_t *p_result_count) 286 { 287 int ok = 0, abort_blocking = 0; 288 RIO_POLL_BUILDER rpb; 289 QUIC_REACTOR_WAIT_CTX wctx; 290 OSSL_TIME earliest_wakeup_deadline; 291 292 /* 293 * Blocking is somewhat involved and involves the following steps: 294 * 295 * - Translation, in which the various logical items (SSL objects, etc.) to 296 * be polled are translated into items an OS polling API understands. 297 * 298 * - Synchronisation bookkeeping. This ensures that we can be woken up 299 * not just by readiness of any underlying file descriptor distilled from 300 * the provided items but also by other threads, which might do work 301 * on a relevant QUIC object to cause the object to be ready without the 302 * underlying file descriptor ever becoming ready from our perspective. 303 * 304 * - The blocking call to the OS polling API. 305 * 306 * - Currently we do not do reverse translation but simply call 307 * poll_readout() again to read out all readiness state for all 308 * descriptors which the user passed. 309 * 310 * TODO(QUIC POLLING): In the future we will do reverse translation here 311 * also to facilitate a more efficient readout. 312 */ 313 ossl_quic_reactor_wait_ctx_init(&wctx); 314 ossl_rio_poll_builder_init(&rpb); 315 316 if (!poll_translate(items, num_items, stride, &wctx, &rpb, 317 &earliest_wakeup_deadline, 318 &abort_blocking, 319 p_result_count)) 320 goto out; 321 322 if (abort_blocking) 323 goto out; 324 325 earliest_wakeup_deadline = ossl_time_min(earliest_wakeup_deadline, 326 user_deadline); 327 328 ok = ossl_rio_poll_builder_poll(&rpb, earliest_wakeup_deadline); 329 330 postpoll_translation_cleanup(items, num_items, stride, &wctx); 331 332 out: 333 ossl_rio_poll_builder_cleanup(&rpb); 334 ossl_quic_reactor_wait_ctx_cleanup(&wctx); 335 return ok; 336 } 337 #endif 338 339 static int poll_readout(SSL_POLL_ITEM *items, 340 size_t num_items, 341 size_t stride, 342 int do_tick, 343 size_t *p_result_count) 344 { 345 int ok = 1; 346 size_t i, result_count = 0; 347 SSL_POLL_ITEM *item; 348 SSL *ssl; 349 #ifndef OPENSSL_NO_QUIC 350 uint64_t events; 351 #endif 352 uint64_t revents; 353 354 for (i = 0; i < num_items; ++i) { 355 item = &ITEM_N(items, stride, i); 356 #ifndef OPENSSL_NO_QUIC 357 events = item->events; 358 #endif 359 revents = 0; 360 361 switch (item->desc.type) { 362 case BIO_POLL_DESCRIPTOR_TYPE_SSL: 363 ssl = item->desc.value.ssl; 364 if (ssl == NULL) 365 /* NULL items are no-ops and have revents reported as 0 */ 366 break; 367 368 switch (ssl->type) { 369 #ifndef OPENSSL_NO_QUIC 370 case SSL_TYPE_QUIC_LISTENER: 371 case SSL_TYPE_QUIC_CONNECTION: 372 case SSL_TYPE_QUIC_XSO: 373 if (!ossl_quic_conn_poll_events(ssl, events, do_tick, &revents)) 374 /* above call raises ERR */ 375 FAIL_ITEM(i); 376 377 if (revents != 0) 378 ++result_count; 379 380 break; 381 #endif 382 383 default: 384 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 385 "SSL_poll currently only supports QUIC SSL " 386 "objects"); 387 FAIL_ITEM(i); 388 } 389 break; 390 case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD: 391 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 392 "SSL_poll currently does not support polling " 393 "sockets"); 394 FAIL_ITEM(i); 395 default: 396 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, 397 "SSL_poll does not support unknown poll descriptor " 398 "type %d", item->desc.type); 399 FAIL_ITEM(i); 400 } 401 402 item->revents = revents; 403 } 404 405 out: 406 if (p_result_count != NULL) 407 *p_result_count = result_count; 408 409 return ok; 410 } 411 412 int SSL_poll(SSL_POLL_ITEM *items, 413 size_t num_items, 414 size_t stride, 415 const struct timeval *timeout, 416 uint64_t flags, 417 size_t *p_result_count) 418 { 419 int ok = 1; 420 size_t result_count = 0; 421 ossl_unused int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0); 422 OSSL_TIME deadline; 423 424 /* Trivial case. */ 425 if (num_items == 0) { 426 if (timeout == NULL) 427 goto out; 428 OSSL_sleep(ossl_time2ms(ossl_time_from_timeval(*timeout))); 429 goto out; 430 } 431 432 /* Convert timeout to deadline. */ 433 if (timeout == NULL) 434 deadline = ossl_time_infinite(); 435 else if (timeout->tv_sec == 0 && timeout->tv_usec == 0) 436 deadline = ossl_time_zero(); 437 else 438 deadline = ossl_time_add(ossl_time_now(), 439 ossl_time_from_timeval(*timeout)); 440 441 /* Loop until we have something to report. */ 442 for (;;) { 443 /* Readout phase - poll current state of each item. */ 444 if (!poll_readout(items, num_items, stride, do_tick, &result_count)) { 445 ok = 0; 446 goto out; 447 } 448 449 /* 450 * If we got anything, or we are in immediate mode (zero timeout), or 451 * the deadline has expired, we're done. 452 */ 453 if (result_count > 0 454 || ossl_time_is_zero(deadline) /* (avoids now call) */ 455 || ossl_time_compare(ossl_time_now(), deadline) >= 0) 456 goto out; 457 458 /* 459 * Block until something is ready. Ignore NO_HANDLE_EVENTS from this 460 * point onwards. 461 */ 462 do_tick = 1; 463 #ifndef OPENSSL_NO_QUIC 464 if (!poll_block(items, num_items, stride, deadline, &result_count)) { 465 ok = 0; 466 goto out; 467 } 468 #endif 469 } 470 471 /* TODO(QUIC POLLING): Support for polling FDs */ 472 473 out: 474 if (p_result_count != NULL) 475 *p_result_count = result_count; 476 477 return ok; 478 } 479