JSSE: fix deadlock issues between SSLSocket close() and OutputStream write()

pull/230/head
Chris Conlon 2024-11-06 10:16:46 -07:00
parent 30e40424a8
commit fe40fe7575
1 changed files with 81 additions and 63 deletions

View File

@ -1937,9 +1937,8 @@ public class WolfSSLSocket extends SSLSocket {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"thread got ioLock (shutdown)"); "thread got ioLock (shutdown)");
synchronized (handshakeLock) { if ((this.getUseClientMode() == true) &&
if (this.getUseClientMode() == true && (handshakeFinished == true)) {
this.handshakeComplete == true) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"saving WOLFSSL_SESSION into cache"); "saving WOLFSSL_SESSION into cache");
EngineHelper.saveSession(); EngineHelper.saveSession();
@ -1949,7 +1948,6 @@ public class WolfSSLSocket extends SSLSocket {
"not saving WOLFSSL_SESSION into cache, " + "not saving WOLFSSL_SESSION into cache, " +
"not client or handshake not complete"); "not client or handshake not complete");
} }
}
try { try {
if (this.socket != null) { if (this.socket != null) {
@ -2001,19 +1999,8 @@ public class WolfSSLSocket extends SSLSocket {
this.EngineHelper.clearObjectState(); this.EngineHelper.clearObjectState();
this.EngineHelper = null; this.EngineHelper = null;
/* Release Input/OutputStream objects. Do not WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
* close WolfSSLSocket inside stream close, "thread exiting handshakeLock (shutdown)");
* since we handle that next below and do
* differently depending on if autoClose has been
* set or not. */
if (this.inStream != null) {
this.inStream.close(false);
this.inStream = null;
}
if (this.outStream != null) {
this.outStream.close(false);
this.outStream = null;
}
} /* handshakeLock */ } /* handshakeLock */
@ -2021,6 +2008,23 @@ public class WolfSSLSocket extends SSLSocket {
"thread exiting ioLock (shutdown)"); "thread exiting ioLock (shutdown)");
} /* ioLock */ } /* ioLock */
/* Release Input/OutputStream objects. Do not close
* WolfSSLSocket inside stream close, since we handle that
* next below and do differently depending on if autoClose
* has been set or not. */
if (this.inStream != null) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"close(), closing InputStream");
this.inStream.close(false);
this.inStream = null;
}
if (this.outStream != null) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"close(), closing OutputStream");
this.outStream.close(false);
this.outStream = null;
}
} }
} }
@ -2457,7 +2461,6 @@ public class WolfSSLSocket extends SSLSocket {
if (isClosing.compareAndSet(false, true)) { if (isClosing.compareAndSet(false, true)) {
synchronized (this) {
if (closeSocket) { if (closeSocket) {
if (this.socket == null || this.isClosed) { if (this.socket == null || this.isClosed) {
return; return;
@ -2477,7 +2480,9 @@ public class WolfSSLSocket extends SSLSocket {
this.socket = null; this.socket = null;
this.ssl = null; this.ssl = null;
this.isClosed = true; this.isClosed = true;
}
/* Reset "is closing" state to false, now closed */
isClosing.set(false);
} }
else { else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
@ -2534,6 +2539,12 @@ public class WolfSSLSocket extends SSLSocket {
throw new NullPointerException("Input array is null"); throw new NullPointerException("Input array is null");
} }
/* check if socket is closing */
if (isClosing.get()) {
throw new SocketException(
"InputStream in process of being closed");
}
/* check if socket is closed */ /* check if socket is closed */
if (this.isClosed || socket == null || socket.isClosed()) { if (this.isClosed || socket == null || socket.isClosed()) {
throw new SocketException("Socket is closed"); throw new SocketException("Socket is closed");
@ -2670,7 +2681,6 @@ public class WolfSSLSocket extends SSLSocket {
if (isClosing.compareAndSet(false, true)) { if (isClosing.compareAndSet(false, true)) {
synchronized (this) {
if (closeSocket) { if (closeSocket) {
if (this.socket == null || this.isClosed) { if (this.socket == null || this.isClosed) {
return; return;
@ -2690,7 +2700,9 @@ public class WolfSSLSocket extends SSLSocket {
this.socket = null; this.socket = null;
this.ssl = null; this.ssl = null;
this.isClosed = true; this.isClosed = true;
}
/* Reset "is closing" state to false, now closed */
isClosing.set(false);
} }
else { else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
@ -2707,14 +2719,14 @@ public class WolfSSLSocket extends SSLSocket {
this.close(true); this.close(true);
} }
public synchronized void write(int b) throws IOException { public void write(int b) throws IOException {
byte[] data = new byte[1]; byte[] data = new byte[1];
data[0] = (byte)(b & 0xFF); data[0] = (byte)(b & 0xFF);
this.write(data, 0, 1); this.write(data, 0, 1);
} }
public synchronized void write(byte[] b) throws IOException { public void write(byte[] b) throws IOException {
this.write(b, 0, b.length); this.write(b, 0, b.length);
} }
@ -2727,6 +2739,12 @@ public class WolfSSLSocket extends SSLSocket {
throw new NullPointerException("Input array is null"); throw new NullPointerException("Input array is null");
} }
/* check if socket is closing */
if (isClosing.get()) {
throw new SocketException(
"OutputStream in process of being closed");
}
/* check if socket is closed */ /* check if socket is closed */
if (this.isClosed || socket == null || socket.isClosed()) { if (this.isClosed || socket == null || socket.isClosed()) {
throw new SocketException("Socket is closed"); throw new SocketException("Socket is closed");