QUIC Channel: Add a mutex
authorHugo Landau <hlandau@openssl.org>
Tue, 21 Feb 2023 10:18:58 +0000 (10:18 +0000)
committerHugo Landau <hlandau@openssl.org>
Thu, 30 Mar 2023 10:14:07 +0000 (11:14 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20348)

include/internal/quic_channel.h
include/internal/quic_ssl.h
ssl/quic/quic_channel.c
ssl/quic/quic_channel_local.h

index f08252d1f9ec115f4346b29982967e7b547e8e2c..13cd83bff12694cb31692498bf36eac8d667c200 100644 (file)
  * demuxers). Since we only use server-side functionality for dummy test servers
  * for now, which only need to handle one connection at a time, this is not
  * currently modelled.
+ *
+ * Synchronisation
+ * ---------------
+ *
+ * To support thread assisted mode, QUIC_CHANNEL can be used by multiple
+ * threads. **It is the caller's responsibility to ensure that the QUIC_CHANNEL
+ * is only accessed (whether via its methods or via direct access to its state)
+ * while the QUIC_CHANNEL mutex is held**, except for methods explicitly marked
+ * as not requiring prior locking. See ossl_quic_channel_get_mutex() for more
+ * information. This is an unchecked precondition.
  */
 
 #  define QUIC_CHANNEL_STATE_IDLE                        0
@@ -198,6 +208,32 @@ QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch);
 
 SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch);
 
+/*
+ * Retreves the channel mutex, which can be used to synchronise access to
+ * channel functions and internal data. In order to allow locks to be acquired
+ * and released with the correct granularity, it is the caller's responsibility
+ * to ensure this lock is held for write while calling any QUIC_CHANNEL method.
+ *
+ * This method is thread safe and does not require prior locking. It can also be
+ * called while the lock is already held.
+ */
+CRYPTO_RWLOCK *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch);
+
+/*
+ * Locks the channel mutex. It is roughly analagous to locking the mutex
+ * returned by ossl_quic_channel_get_mutex() but might be able to avoid locking
+ * where thread assisted mode is not being used, thus it is recommended that
+ * these methods are used uniformly rather than locking the channel mutex
+ * directly.
+ *
+ * This method is (obviously) thread safe and does not require prior locking. It
+ * must not be called while the lock is already held.
+ */
+int ossl_quic_channel_lock(QUIC_CHANNEL *ch);
+
+/* Unlocks the channel mutex. */
+void ossl_quic_channel_unlock(QUIC_CHANNEL *ch);
+
 # endif
 
 #endif
index 7b89534c22ec1cfb3d2331e79aa55009b1e89b37..3cf32e0944c8d2cf2d5396cacdaf7e6574ec3cc5 100644 (file)
@@ -46,6 +46,7 @@ void ossl_quic_set_accept_state(QUIC_CONNECTION *qc);
 __owur int ossl_quic_has_pending(const QUIC_CONNECTION *qc);
 __owur int ossl_quic_tick(QUIC_CONNECTION *qc);
 __owur int ossl_quic_get_tick_timeout(QUIC_CONNECTION *qc, struct timeval *tv);
+OSSL_TIME ossl_quic_get_tick_deadline(QUIC_CONNECTION *qc);
 __owur int ossl_quic_get_rpoll_descriptor(QUIC_CONNECTION *qc, BIO_POLL_DESCRIPTOR *d);
 __owur int ossl_quic_get_wpoll_descriptor(QUIC_CONNECTION *qc, BIO_POLL_DESCRIPTOR *d);
 __owur int ossl_quic_get_net_read_desired(QUIC_CONNECTION *qc);
index 86eed313ab447a4f1294db80d53e3e7e9255287c..efe8ca6def0488d80516009ed3d8be43165f3033 100644 (file)
@@ -115,6 +115,10 @@ static int ch_init(QUIC_CHANNEL *ch)
     qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN;
     ch->rx_max_udp_payload_size = qtx_args.mdpl;
 
+    ch->mutex = CRYPTO_THREAD_lock_new();
+    if (ch->mutex == NULL)
+        goto err;
+
     ch->qtx = ossl_qtx_new(&qtx_args);
     if (ch->qtx == NULL)
         goto err;
@@ -318,6 +322,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch)
     ossl_qrx_free(ch->qrx);
     ossl_quic_demux_free(ch->demux);
     OPENSSL_free(ch->local_transport_params);
+    CRYPTO_THREAD_lock_free(ch->mutex);
 }
 
 QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args)
@@ -443,6 +448,21 @@ QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch)
     return ch->demux;
 }
 
+CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch)
+{
+    return ch->mutex;
+}
+
+int ossl_quic_channel_lock(QUIC_CHANNEL *ch)
+{
+    return ossl_crypto_mutex_lock(ch->mutex);
+}
+
+void ossl_quic_channel_unlock(QUIC_CHANNEL *ch)
+{
+    ossl_crypto_mutex_unlock(ch->mutex);
+}
+
 /*
  * QUIC Channel: Callbacks from Miscellaneous Subsidiary Components
  * ================================================================
index fa2618bce54c0fc2a4a2cb291dc8ad4fa7718c83..2f63119cef538c1f1eec6bebd610d7048a92f8e3 100644 (file)
@@ -25,6 +25,12 @@ struct quic_channel_st {
     OSSL_LIB_CTX                    *libctx;
     const char                      *propq;
 
+    /*
+     * Master synchronisation mutex used for thread assisted mode
+     * synchronisation.
+     */
+    CRYPTO_RWLOCK                   *mutex;
+
     /*
      * The associated TLS 1.3 connection data. Used to provide the handshake
      * layer; its 'network' side is plugged into the crypto stream for each EL