Add whitelist entry to BlockHound config to workaround issue when TLS… (#10459)

Motivation:

SSLEngineImpl.unwrap(...) may call FileInputStream.read(...) internally when TLS1.3 is used. This will cause an BlockingOperationError when BlockHound is enabled.

For more details see https://mail.openjdk.java.net/pipermail/security-dev/2020-August/022271.html

Modifications:

- Add whitelist entry to BlockHound config for now
- Update NettyBlockHoundIntegrationTest to include testing for this workaround

Result:

No BlockingOperationError when TLS1.3 is used with JDK SSL implementation and BlockHound is enabled
This commit is contained in:
Norman Maurer 2020-08-10 11:10:35 +02:00
parent 2b73c93581
commit 6fd5550ad7
2 changed files with 61 additions and 12 deletions

View File

@ -76,6 +76,12 @@ class Hidden {
"io.netty.handler.ssl.ReferenceCountedOpenSslClientContext$ExtendedTrustManagerVerifyCallback",
"verify");
// Let's whitelist SSLEngineImpl.unwrap(...) for now as it may fail otherwise for TLS 1.3.
// See https://mail.openjdk.java.net/pipermail/security-dev/2020-August/022271.html
builder.allowBlockingCallsInside(
"sun.security.ssl.SSLEngineImpl",
"unwrap");
builder.nonBlockingThreadPredicate(p -> thread ->
p.test(thread) || thread instanceof FastThreadLocalThread);
}

View File

@ -56,8 +56,8 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
public class NettyBlockHoundIntegrationTest {
@ -96,24 +96,53 @@ public class NettyBlockHoundIntegrationTest {
// Tests copied from io.netty.handler.ssl.SslHandlerTest
@Test
public void testHandshakeWithExecutorThatExecuteDirectory() throws Exception {
testHandshakeWithExecutor(Runnable::run);
testHandshakeWithExecutor(Runnable::run, "TLSv1.2");
}
@Test
public void testHandshakeWithExecutorThatExecuteDirectoryTLSv13() throws Exception {
assumeTrue(SslProvider.isTlsv13Supported(SslProvider.JDK));
testHandshakeWithExecutor(Runnable::run, "TLSv1.3");
}
@Test
public void testHandshakeWithImmediateExecutor() throws Exception {
testHandshakeWithExecutor(ImmediateExecutor.INSTANCE);
testHandshakeWithExecutor(ImmediateExecutor.INSTANCE, "TLSv1.2");
}
@Test
public void testHandshakeWithImmediateExecutorTLSv13() throws Exception {
assumeTrue(SslProvider.isTlsv13Supported(SslProvider.JDK));
testHandshakeWithExecutor(ImmediateExecutor.INSTANCE, "TLSv1.3");
}
@Test
public void testHandshakeWithImmediateEventExecutor() throws Exception {
testHandshakeWithExecutor(ImmediateEventExecutor.INSTANCE);
testHandshakeWithExecutor(ImmediateEventExecutor.INSTANCE, "TLSv1.2");
}
@Test
public void testHandshakeWithImmediateEventExecutorTLSv13() throws Exception {
assumeTrue(SslProvider.isTlsv13Supported(SslProvider.JDK));
testHandshakeWithExecutor(ImmediateEventExecutor.INSTANCE, "TLSv1.3");
}
@Test
public void testHandshakeWithExecutor() throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
testHandshakeWithExecutor(executorService);
testHandshakeWithExecutor(executorService, "TLSv1.2");
} finally {
executorService.shutdown();
}
}
@Test
public void testHandshakeWithExecutorTLSv13() throws Exception {
assumeTrue(SslProvider.isTlsv13Supported(SslProvider.JDK));
ExecutorService executorService = Executors.newCachedThreadPool();
try {
testHandshakeWithExecutor(executorService, "TLSv1.3");
} finally {
executorService.shutdown();
}
@ -121,15 +150,30 @@ public class NettyBlockHoundIntegrationTest {
@Test
public void testTrustManagerVerify() throws Exception {
testTrustManagerVerify("TLSv1.2");
}
@Test
public void testTrustManagerVerifyTLSv13() throws Exception {
assumeTrue(SslProvider.isTlsv13Supported(SslProvider.JDK));
testTrustManagerVerify("TLSv1.3");
}
private static void testTrustManagerVerify(String tlsVersion) throws Exception {
final SslContext sslClientCtx =
SslContextBuilder.forClient()
.trustManager(ResourcesUtil.getFile(getClass(), "mutual_auth_ca.pem"))
.protocols(tlsVersion)
.trustManager(ResourcesUtil.getFile(
NettyBlockHoundIntegrationTest.class, "mutual_auth_ca.pem"))
.build();
final SslContext sslServerCtx =
SslContextBuilder.forServer(ResourcesUtil.getFile(getClass(), "localhost_server.pem"),
ResourcesUtil.getFile(getClass(), "localhost_server.key"),
SslContextBuilder.forServer(ResourcesUtil.getFile(
NettyBlockHoundIntegrationTest.class, "localhost_server.pem"),
ResourcesUtil.getFile(
NettyBlockHoundIntegrationTest.class, "localhost_server.key"),
null)
.protocols(tlsVersion)
.build();
final SslHandler clientSslHandler = sslClientCtx.newHandler(UnpooledByteBufAllocator.DEFAULT);
@ -138,8 +182,7 @@ public class NettyBlockHoundIntegrationTest {
testHandshake(sslClientCtx, clientSslHandler, serverSslHandler);
}
private static void testHandshakeWithExecutor(Executor executor) throws Exception {
String tlsVersion = "TLSv1.2";
private static void testHandshakeWithExecutor(Executor executor, String tlsVersion) throws Exception {
final SslContext sslClientCtx = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.sslProvider(SslProvider.JDK).protocols(tlsVersion).build();
@ -189,8 +232,8 @@ public class NettyBlockHoundIntegrationTest {
}).connect(sc.localAddress());
cc = future.syncUninterruptibly().channel();
assertTrue(clientSslHandler.handshakeFuture().await().isSuccess());
assertTrue(serverSslHandler.handshakeFuture().await().isSuccess());
clientSslHandler.handshakeFuture().await().sync();
serverSslHandler.handshakeFuture().await().sync();
} finally {
if (cc != null) {
cc.close().syncUninterruptibly();