mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-09 22:30:52 +02:00
Address review: probe the DTLS socket type where the fd is set
Under WOLFSSL_RW_THREADED the read and write threads could both perform the lazy isDGramSock() first-time cache write concurrently; the cached bit-fields share a storage unit with other dtlsCtx flags, making this a data race. Instead of caching from inside the I/O callbacks, run the getsockopt(SO_TYPE) probe where dtlsCtx.rfd/wfd is assigned and store the result per descriptor (rfd and wfd may be different sockets of different types). fd assignment happens during single-threaded setup, so no thread-specific handling is needed, and the I/O callbacks reduce to reading a struct member, so isDGramSock() is dropped in favor of reading the flags directly. The stateless-hash test no longer needs to mask the fields: the I/O callbacks no longer write to the WOLFSSL object.
This commit is contained in:
+2
-1
@@ -7945,7 +7945,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
|
||||
ssl->buffers.dtlsCtx.rfd = -1;
|
||||
ssl->buffers.dtlsCtx.wfd = -1;
|
||||
ssl->buffers.dtlsCtx.isDGramCached = 0;
|
||||
ssl->buffers.dtlsCtx.rfdIsDGram = 0;
|
||||
ssl->buffers.dtlsCtx.wfdIsDGram = 0;
|
||||
|
||||
#ifdef WOLFSSL_RW_THREADED
|
||||
if (wc_InitRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
|
||||
|
||||
@@ -1131,7 +1131,10 @@ int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.rfd = fd;
|
||||
ssl->buffers.dtlsCtx.isDGramCached = 0;
|
||||
#ifdef USE_WOLFSSL_IO
|
||||
ssl->buffers.dtlsCtx.rfdIsDGram =
|
||||
(byte)(wolfIO_SockIsDGram(fd) != 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1156,7 +1159,10 @@ int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.wfd = fd;
|
||||
ssl->buffers.dtlsCtx.isDGramCached = 0;
|
||||
#ifdef USE_WOLFSSL_IO
|
||||
ssl->buffers.dtlsCtx.wfdIsDGram =
|
||||
(byte)(wolfIO_SockIsDGram(fd) != 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6821,7 +6827,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.rfd = rfd;
|
||||
ssl->buffers.dtlsCtx.isDGramCached = 0;
|
||||
#ifdef USE_WOLFSSL_IO
|
||||
ssl->buffers.dtlsCtx.rfdIsDGram =
|
||||
(byte)(wolfIO_SockIsDGram(rfd) != 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+8
-13
@@ -643,27 +643,22 @@ static int PeerIsIpv6(const SOCKADDR_S *peer, XSOCKLENT len)
|
||||
#endif /* !WOLFSSL_IPV6 */
|
||||
|
||||
/* Return non-zero iff sfd is a SOCK_DGRAM socket. A descriptor's type is
|
||||
* fixed for its lifetime, so the getsockopt(SO_TYPE) probe runs once per
|
||||
* connection and is cached in dtlsCtx; the cache is invalidated wherever
|
||||
* rfd/wfd is reassigned. */
|
||||
static int isDGramSock(WOLFSSL_DTLS_CTX* dtlsCtx, int sfd)
|
||||
* fixed for its lifetime, so the probe runs where dtlsCtx.rfd/wfd is
|
||||
* assigned and the result is stored alongside the descriptor, keeping the
|
||||
* getsockopt() syscall out of the I/O callbacks. */
|
||||
int wolfIO_SockIsDGram(int sfd)
|
||||
{
|
||||
int type = 0;
|
||||
/* optvalue 'type' is of size int */
|
||||
XSOCKLENT length = (XSOCKLENT)sizeof(type);
|
||||
|
||||
if (dtlsCtx->isDGramCached)
|
||||
return dtlsCtx->isDGram;
|
||||
|
||||
if (getsockopt(sfd, SOL_SOCKET, SO_TYPE, (XSOCKOPT_TYPE_OPTVAL_TYPE)&type,
|
||||
&length) == 0 && type != SOCK_DGRAM) {
|
||||
dtlsCtx->isDGram = 0;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
dtlsCtx->isDGram = 1;
|
||||
return 1;
|
||||
}
|
||||
dtlsCtx->isDGramCached = 1;
|
||||
return dtlsCtx->isDGram;
|
||||
}
|
||||
|
||||
void wolfSSL_SetRecvFrom(WOLFSSL* ssl, WolfSSLRecvFrom recvFrom)
|
||||
@@ -853,7 +848,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
||||
return recvd;
|
||||
}
|
||||
else if (recvd == 0) {
|
||||
if (!isDGramSock(dtlsCtx, sd)) {
|
||||
if (!dtlsCtx->rfdIsDGram) {
|
||||
/* Closed TCP connection */
|
||||
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
||||
}
|
||||
@@ -951,7 +946,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
|
||||
if (sz < 0)
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
|
||||
if (!isDGramSock(dtlsCtx, sd)) {
|
||||
if (!dtlsCtx->wfdIsDGram) {
|
||||
/* Probably a TCP socket. peer and peerSz MUST be NULL and 0 */
|
||||
}
|
||||
else if (!dtlsCtx->connected) {
|
||||
|
||||
@@ -3613,10 +3613,6 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl)
|
||||
sslCopy.dtls13FastTimeout = 0;
|
||||
#endif
|
||||
sslCopy.keys.dtls_peer_handshake_number = 0;
|
||||
/* isDGram* is a local-socket-type memoization the IO callbacks may
|
||||
* populate lazily; it is not peer state and not relevant here. */
|
||||
sslCopy.buffers.dtlsCtx.isDGramCached = 0;
|
||||
sslCopy.buffers.dtlsCtx.isDGram = 0;
|
||||
XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history));
|
||||
sslCopy.hsHashes = NULL;
|
||||
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
|
||||
|
||||
+5
-4
@@ -2791,10 +2791,11 @@ typedef struct WOLFSSL_DTLS_CTX {
|
||||
* connected (connect() and bind() both called).
|
||||
* This means that sendto and recvfrom do not need to
|
||||
* specify and store the peer address. */
|
||||
byte isDGramCached:1; /* whether isDGram below is valid; reset whenever
|
||||
* rfd/wfd is (re)assigned so the SO_TYPE probe
|
||||
* re-runs once for the new descriptor. */
|
||||
byte isDGram:1; /* cached isDGramSock() for the rfd/wfd socket */
|
||||
byte rfdIsDGram:1; /* whether rfd is a SOCK_DGRAM socket; probed with
|
||||
* getsockopt(SO_TYPE) where rfd is assigned to keep
|
||||
* the syscall out of the I/O callbacks. */
|
||||
byte wfdIsDGram:1; /* as rfdIsDGram, for wfd; rfd and wfd may be
|
||||
* different sockets of different types. */
|
||||
#ifdef WOLFSSL_DTLS_CID
|
||||
byte processingPendingRecord:1;
|
||||
#endif
|
||||
|
||||
@@ -703,6 +703,7 @@ WOLFSSL_LOCAL int SslBioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx);
|
||||
WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx);
|
||||
WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz,
|
||||
void *ctx);
|
||||
WOLFSSL_LOCAL int wolfIO_SockIsDGram(int sfd);
|
||||
#ifdef WOLFSSL_MULTICAST
|
||||
WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf,
|
||||
int sz, void *ctx);
|
||||
|
||||
Reference in New Issue
Block a user