mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-01 19:44:44 +00:00
Fix SIGSEGV when closing SSL async socket while sending/receiving (#24795)
Async SSL socket SIGSEGV's sometimes when calling socket.close() while
send/recv. The issue was found here
https://github.com/nitely/nim-hyperx/pull/59.
Possibly related: #24024
This can occur when closing the socket while sending or receiving,
because `socket.sslHandle` is freed. The sigsegv can also occur on calls
that require `socket.bioIn` or `socket.bioOut` because those use
`socket.sslHandle` internally. This PR checks sslHandle is set before
doing any operation that requires it.
(cherry picked from commit 9ace1f97ac)
This commit is contained in:
committed by
narimiran
parent
4d41384f09
commit
e799d2fca0
@@ -207,6 +207,9 @@ proc newAsyncSocket*(domain, sockType, protocol: cint,
|
|||||||
Protocol(protocol), buffered, inheritable)
|
Protocol(protocol), buffered, inheritable)
|
||||||
|
|
||||||
when defineSsl:
|
when defineSsl:
|
||||||
|
proc raiseSslHandleError =
|
||||||
|
raiseSSLError("The SSL Handle is closed/unset")
|
||||||
|
|
||||||
proc getSslError(socket: AsyncSocket, err: cint): cint =
|
proc getSslError(socket: AsyncSocket, err: cint): cint =
|
||||||
assert socket.isSsl
|
assert socket.isSsl
|
||||||
assert err < 0
|
assert err < 0
|
||||||
@@ -227,6 +230,8 @@ when defineSsl:
|
|||||||
|
|
||||||
proc sendPendingSslData(socket: AsyncSocket,
|
proc sendPendingSslData(socket: AsyncSocket,
|
||||||
flags: set[SocketFlag]) {.async.} =
|
flags: set[SocketFlag]) {.async.} =
|
||||||
|
if socket.sslHandle == nil:
|
||||||
|
raiseSslHandleError()
|
||||||
let len = bioCtrlPending(socket.bioOut)
|
let len = bioCtrlPending(socket.bioOut)
|
||||||
if len > 0:
|
if len > 0:
|
||||||
var data = newString(len)
|
var data = newString(len)
|
||||||
@@ -246,6 +251,8 @@ when defineSsl:
|
|||||||
await sendPendingSslData(socket, flags)
|
await sendPendingSslData(socket, flags)
|
||||||
of SSL_ERROR_WANT_READ:
|
of SSL_ERROR_WANT_READ:
|
||||||
var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
|
var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
|
||||||
|
if socket.sslHandle == nil:
|
||||||
|
raiseSslHandleError()
|
||||||
let length = len(data)
|
let length = len(data)
|
||||||
if length > 0:
|
if length > 0:
|
||||||
let ret = bioWrite(socket.bioIn, cast[cstring](addr data[0]), length.cint)
|
let ret = bioWrite(socket.bioIn, cast[cstring](addr data[0]), length.cint)
|
||||||
@@ -262,6 +269,8 @@ when defineSsl:
|
|||||||
op: untyped) =
|
op: untyped) =
|
||||||
var opResult {.inject.} = -1.cint
|
var opResult {.inject.} = -1.cint
|
||||||
while opResult < 0:
|
while opResult < 0:
|
||||||
|
if socket.sslHandle == nil:
|
||||||
|
raiseSslHandleError()
|
||||||
ErrClearError()
|
ErrClearError()
|
||||||
# Call the desired operation.
|
# Call the desired operation.
|
||||||
opResult = op
|
opResult = op
|
||||||
@@ -306,6 +315,8 @@ proc connect*(socket: AsyncSocket, address: string, port: Port) {.async.} =
|
|||||||
await connect(socket.fd.AsyncFD, address, port, socket.domain)
|
await connect(socket.fd.AsyncFD, address, port, socket.domain)
|
||||||
if socket.isSsl:
|
if socket.isSsl:
|
||||||
when defineSsl:
|
when defineSsl:
|
||||||
|
if socket.sslHandle == nil:
|
||||||
|
raiseSslHandleError()
|
||||||
if not isIpAddress(address):
|
if not isIpAddress(address):
|
||||||
# Set the SNI address for this connection. This call can fail if
|
# Set the SNI address for this connection. This call can fail if
|
||||||
# we're not using TLSv1+.
|
# we're not using TLSv1+.
|
||||||
@@ -727,6 +738,8 @@ proc close*(socket: AsyncSocket) =
|
|||||||
defer:
|
defer:
|
||||||
socket.fd.AsyncFD.closeSocket()
|
socket.fd.AsyncFD.closeSocket()
|
||||||
socket.closed = true # TODO: Add extra debugging checks for this.
|
socket.closed = true # TODO: Add extra debugging checks for this.
|
||||||
|
when defineSsl:
|
||||||
|
socket.sslHandle = nil
|
||||||
|
|
||||||
when defineSsl:
|
when defineSsl:
|
||||||
if socket.isSsl:
|
if socket.isSsl:
|
||||||
|
|||||||
Reference in New Issue
Block a user