JDK-8215790 : Delegated task created by SSLEngine throws java.nio.BufferUnderflowException
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 11,12
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2018-12-19
  • Updated: 2020-11-19
  • Resolved: 2019-02-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12 JDK 13 JDK 8 Other
11.0.4-oracleFixed 12.0.2Fixed 13 b08Fixed 8u261Fixed openjdk8u272Fixed
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

A DESCRIPTION OF THE PROBLEM :
Occasionally we see stack traces like the following on our production servers

Exception in thread "main" java.nio.BufferUnderflowException
	at java.base/java.nio.Buffer.nextGetIndex(Buffer.java:641)
	at java.base/java.nio.HeapByteBuffer.get(HeapByteBuffer.java:162)
	at java.base/sun.security.ssl.ClientHello$ClientHelloMessage.<init>(ClientHello.java:166)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:803)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999)
	at ... application specific methods ...
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)

Is it expected behavior for delegated tasks created by javax.net.ssl.SSLEngine to throw RuntimeExceptions of type java.nio.BufferUnderflowException?

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Not reproducible, happens occasionally on production servers.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No RuntimeExceptions are thrown from delegated tasks created by javax.net.ssl.SSLEngine.
ACTUAL -
RuntimeExceptions are thrown from delegated tasks created by javax.net.ssl.SSLEngine.

FREQUENCY : occasionally



Comments
Fix Request This patch fixes the corner case in SSL handling. The patch applies cleanly to 12u and [after JDK-8215443 backport] to 11u. Passes jdk_security test suite in both 12u and 11u after the patch, which includes the new regression test. New regression test fails without the patch.
12-03-2019

I had a quick search, it looks like other handshake messages parsing implementation also have similar issues, for example ServerHello could throw BufferUnderflowException is the ByteBuff is illegal. BufferUnderflowException might be a common issue for all handshake message decoding. We might need a general solution for this kind of RuntimeException. I filed a new bug (JDK-8219389) to address the issues.
19-02-2019

Reopening as the submitter did come back with more information that it is about RuntimeExceptions not being wrapped in SSLException.
31-01-2019

From submitter: In my opinion, the behavior of JDK 11 and JDK 12-ea violates the API specification for class javax.net.ssl.SSLEngine (see [1], [2]). The exception should be wrapped into a javax.net.ssl.SSLException as in JDK versions prior to JDK 11. By throwing new types of exceptions not documented in the API specification, JDK 11 and 12-ea are likely to break existing clients of class javax.net.ssl.SSLEngine. [1] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLEngine.html#unwrap(java.nio.ByteBuffer,java.nio.ByteBuffer) [2] https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLEngine.html#wrap(java.nio.ByteBuffer,java.nio.ByteBuffer)
17-01-2019

Sent an email to submitter for the clarification .
17-01-2019

Could you please clarify, is this bug about the occasionally failures with the ByteBuffer or is the bug whether the exception should be wrapped in SSLException?
16-01-2019

Additional Information: We have now a reproducible test case based on jdk11u-8513ac27b651/test/jdk/javax/net/ssl/interop/ClientHelloChromeInterOp.java ================================================================================ import sun.security.util.HexDumpEncoder; public class ClientHelloBufferUnderflowException extends ClientHelloInterOp { /* * Main entry point for this test. */ public static void main(String args[]) throws Exception { (new ClientHelloBufferUnderflowException()).run(); } @Override protected byte[] createClientHelloMessage() { // The ClientHello message in hex: 16 03 01 00 05 01 00 00 01 03 // Record Header: // 16 - type is 0x16 (handshake record) // 03 01 - protocol version is 3.1 (also known as TLS 1.0) // 00 05 - 0x05 (5) bytes of handshake message follows // Handshake Header: // 01 - handshake message type 0x01 (client hello) // 00 00 01 - 0x01 (1) bytes of client hello follows // Client Version: // 03 - incomplete client version // // (Based on https://tls.ulfheim.net) byte[] bytes = { 0x16, 0x03, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01, 0x03}; System.out.println("The ClientHello message used"); try { (new HexDumpEncoder()).encodeBuffer(bytes, System.out); } catch (Exception e) { // ignore } return bytes; } } ================================================================================ Below, three test runs based on different JDK builds demonstrating a regression from JDK 10.0.2 (build 10.0.2+13) which correctly reports an exception of type javax.net.ssl.SSLException to JDK 11.0.1 (build 11.0.1+13) and JDK 12-ea (build 12-ea+24) which both produce an exception of type java.nio.BufferUnderflowException. The behavior of JDK 11.0.1 and JDK 12-ea seems to violate the API specification for class javax.net.ssl.SSLEngine. ================================================================================ $ ../jdk-10.0.2/bin/java -version openjdk version "10.0.2" 2018-07-17 OpenJDK Runtime Environment 18.3 (build 10.0.2+13) OpenJDK 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode) $ ../jdk-10.0.2/bin/java ClientHelloBufferUnderflowException The ClientHello message used 0000: 16 03 01 00 05 01 00 00 01 03 .......... Server unwrap: OK/NEED_TASK, consumed: 10/produced: 0 bytes running delegated task... new HandshakeStatus: NEED_UNWRAP Exception in thread "main" javax.net.ssl.SSLException: Unexpected end of handshake data at java.base/sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1618) at java.base/sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:497) at java.base/sun.security.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1282) at java.base/sun.security.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1256) at java.base/javax.net.ssl.SSLEngine.wrap(SSLEngine.java:471) at ClientHelloInterOp.run(ClientHelloInterOp.java:217) at ClientHelloBufferUnderflowException.main(ClientHelloBufferUnderflowException.java:8) Caused by: javax.net.ssl.SSLException: Unexpected end of handshake data at java.base/sun.security.ssl.HandshakeInStream.verifyLength(HandshakeInStream.java:176) at java.base/sun.security.ssl.HandshakeInStream.getInt8(HandshakeInStream.java:123) at java.base/sun.security.ssl.HandshakeMessage$ClientHello.<init>(HandshakeMessage.java:347) at java.base/sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:232) at java.base/sun.security.ssl.Handshaker.processLoop(Handshaker.java:1098) at java.base/sun.security.ssl.Handshaker$1.run(Handshaker.java:1031) at java.base/sun.security.ssl.Handshaker$1.run(Handshaker.java:1028) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1540) at ClientHelloInterOp.runDelegatedTasks(ClientHelloInterOp.java:400) at ClientHelloInterOp.run(ClientHelloInterOp.java:207) ... 1 more ================================================================================ ================================================================================ $ ../jdk-11.0.1/bin/java -version openjdk version "11.0.1" 2018-10-16 OpenJDK Runtime Environment 18.9 (build 11.0.1+13) OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode) $ ../jdk-11.0.1/bin/java ClientHelloBufferUnderflowException The ClientHello message used 0000: 16 03 01 00 05 01 00 00 01 03 .......... Server unwrap: OK/NEED_TASK, consumed: 10/produced: 0 bytes running delegated task... new HandshakeStatus: NEED_UNWRAP Exception in thread "main" java.nio.BufferUnderflowException at java.base/java.nio.Buffer.nextGetIndex(Buffer.java:641) at java.base/java.nio.HeapByteBuffer.get(HeapByteBuffer.java:162) at java.base/sun.security.ssl.ClientHello$ClientHelloMessage.<init>(ClientHello.java:166) at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:803) at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999) at ClientHelloInterOp.runDelegatedTasks(ClientHelloInterOp.java:400) at ClientHelloInterOp.run(ClientHelloInterOp.java:207) at ClientHelloBufferUnderflowException.main(ClientHelloBufferUnderflowException.java:8) ================================================================================ ================================================================================ $ ../jdk-12/bin/java -version openjdk version "12-ea" 2019-03-19 OpenJDK Runtime Environment (build 12-ea+24) OpenJDK 64-Bit Server VM (build 12-ea+24, mixed mode, sharing) $ ../jdk-12/bin/java ClientHelloBufferUnderflowException The ClientHello message used 0000: 16 03 01 00 05 01 00 00 01 03 .......... Server unwrap: OK/NEED_TASK, consumed: 10/produced: 0 bytes running delegated task... new HandshakeStatus: NEED_UNWRAP Exception in thread "main" java.nio.BufferUnderflowException at java.base/java.nio.Buffer.nextGetIndex(Buffer.java:641) at java.base/java.nio.HeapByteBuffer.get(HeapByteBuffer.java:162) at java.base/sun.security.ssl.ClientHello$ClientHelloMessage.<init>(ClientHello.java:166) at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:803) at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:448) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052) at java.base/java.security.AccessController.doPrivileged(AccessController.java:688) at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999) at ClientHelloInterOp.runDelegatedTasks(ClientHelloInterOp.java:400) at ClientHelloInterOp.run(ClientHelloInterOp.java:207) at ClientHelloBufferUnderflowException.main(ClientHelloBufferUnderflowException.java:8) ================================================================================ Additional Information: In the meantime, we noticed that RuntimeExceptions are correctly captured in sun.security.ssl.SSLEngineImpl$DelegatedTask.run. Subsequently they are rethrown in sun.security.ssl.SSLEngineImpl.wrap or sun.security.ssl.SSLEngineImpl.unwrap. The underlying question remains the same: Is it expected behavior that RuntimeExceptions like java.nio.BufferUnderflowException get propagated through the interface of javax.net.ssl.SSLEngine? Should such exceptions not be handled (and possibly wrapped into an exception of type javax.net.ssl.SSLException) as part of the implementation of javax.net.ssl.SSLEngine?
09-01-2019

Please try with JDK 12 ea+24 posted on http://jdk.java.net/12/. Closing as Incomplete for now, will reopen if there is a pattern to reproduce the issue.
21-12-2018