https://bz.apache.org/bugzilla/show_bug.cgi?id=61998
Bug ID: 61998
Summary: tomcat: dead loop in the processing of SSL handshake
Product: Tomcat 8
Version: 8.5.15
Hardware: PC
OS: Linux
Status: NEW
Severity: critical
Priority: P2
Component: Util
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ----
During our https attack test, a dead loop has happened in
org.apache.tomcat.util.net.SecureNioChannel#handshake.
A lot of(million) packets were sent during the test so it's extremely hard to
find which one caused the problem.
The dead loop didn't stop even after we had stopped the test.
I've debugged tomcat using jdb. The results are as follows.
while (!handshakeComplete) {
switch ( handshakeStatus ) {
//handshakeStatus = NEED_UNWRAP
//...
case NEED_UNWRAP: {
//perform the unwrap function
handshake = handshakeUnwrap(read);
//handshake.getStatus() = Status.BUFFER_OVERFLOW
if ( handshake.getStatus() == Status.OK ) {
if (handshakeStatus == HandshakeStatus.NEED_TASK)
handshakeStatus = tasks();
} else if ( handshake.getStatus() == Status.BUFFER_UNDERFLOW ){
//read more data, reregister for OP_READ
return SelectionKey.OP_READ;
} else if (handshake.getStatus() == Status.BUFFER_OVERFLOW) {
getBufHandler().configureReadBufferForWrite();
} else {
throw new
IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap",
handshakeStatus));
}//switch
break;
}
case NEED_TASK: {
handshakeStatus = tasks();
break;
}
default: throw new
IllegalStateException(sm.getString("channel.nio.ssl.invalidStatus",
handshakeStatus));
}
}
protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {
if (netInBuffer.position() == netInBuffer.limit()) {
//clear the buffer if we have emptied it out on data
netInBuffer.clear();
}
/**
Value of netInBuffer here.
https-jsse-nio-20000-exec-38[1] dump netInBuffer
netInBuffer = {
java.nio.ByteBuffer.hb: instance of byte[16921] (id=9332)
java.nio.ByteBuffer.offset: 0
java.nio.ByteBuffer.isReadOnly: false
java.nio.ByteBuffer.bigEndian: true
java.nio.ByteBuffer.nativeByteOrder: false
java.nio.Buffer.SPLITERATOR_CHARACTERISTICS: 16464
java.nio.Buffer.mark: -1
java.nio.Buffer.position: 16
java.nio.Buffer.limit: 16921
java.nio.Buffer.capacity: 16921
java.nio.Buffer.address: 0
}
*
/
if ( doread ) {
//if we have data to read, read it
int read = sc.read(netInBuffer);
//read = 0
if (read == -1) throw new
IOException(sm.getString("channel.nio.ssl.eofDuringHandshake"));
}
SSLEngineResult result;
boolean cont = false;
//loop while we can perform pure SSLEngine data
do {
//prepare the buffer with the incoming data
netInBuffer.flip();
//call unwrap
getBufHandler().configureReadBufferForWrite();
result = sslEngine.unwrap(netInBuffer,
getBufHandler().getReadBuffer()); //result: "Status =
BUFFER_OVERFLOW HandshakeStatus = NEED_UNWRAP bytesConsumed = 0 bytesProduced =
0"
//compact the buffer, this is an optional method, wonder what would
happen if we didn't
netInBuffer.compact();
//read in the status
handshakeStatus = result.getHandshakeStatus();
if ( result.getStatus() == SSLEngineResult.Status.OK &&
result.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) {
//execute tasks if we need to
handshakeStatus = tasks();
}
//perform another unwrap?
cont = result.getStatus() == SSLEngineResult.Status.OK &&
handshakeStatus == HandshakeStatus.NEED_UNWRAP;
}while ( cont );
return result;
}
Since sc.read(netInBuffer) returns 0, I'm wondering configuring timeout,
keepalive or something else to avoid the problem.
I'd appreciated if you can confirm if there is a bug or have any suggestions to
avoid the problem.
Thanks a lot.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]