Add whitelist entry for SSLEngineImpl.wrap to BlockHound configuration (#10844)

Motivation:

Internally SSLEngineImpl.wrap(...) may call FileInputStream.read(...).
This will cause the error below when BlockHound is enabled
reactor.blockhound.BlockingOperationError: Blocking call! java.io.FileInputStream#readBytes
	at java.io.FileInputStream.readBytes(FileInputStream.java)
	at java.io.FileInputStream.read(FileInputStream.java:255)

Modifications:

- Add whitelist entry to BlockHound configuration
- Add test

Result:

Fixes #10837
This commit is contained in:
Violeta Georgieva 2020-12-07 09:06:21 +02:00 committed by Norman Maurer
parent a06c6f8916
commit 4c86fbd967
2 changed files with 80 additions and 0 deletions

View File

@ -105,6 +105,10 @@ class Hidden {
"sun.security.ssl.SSLEngineImpl",
"unwrap");
builder.allowBlockingCallsInside(
"sun.security.ssl.SSLEngineImpl",
"wrap");
builder.nonBlockingThreadPredicate(p -> thread ->
p.test(thread) || thread instanceof FastThreadLocalThread);
}

View File

@ -20,6 +20,7 @@ import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
@ -63,9 +64,13 @@ import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import static io.netty.buffer.Unpooled.wrappedBuffer;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@ -238,6 +243,77 @@ public class NettyBlockHoundIntegrationTest {
testTrustManagerVerify("TLSv1.3");
}
@Test
public void testSslHandlerWrapAllowsBlockingCalls() throws Exception {
final SslContext sslClientCtx =
SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.sslProvider(SslProvider.JDK)
.build();
final SslHandler sslHandler = sslClientCtx.newHandler(UnpooledByteBufAllocator.DEFAULT);
final EventLoopGroup group = new NioEventLoopGroup();
final CountDownLatch activeLatch = new CountDownLatch(1);
final AtomicReference<Throwable> error = new AtomicReference<>();
Channel sc = null;
Channel cc = null;
try {
sc = new ServerBootstrap()
.group(group)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInboundHandlerAdapter())
.bind(new InetSocketAddress(0))
.syncUninterruptibly()
.channel();
cc = new Bootstrap()
.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(sslHandler);
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) {
activeLatch.countDown();
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
if (evt instanceof SslHandshakeCompletionEvent &&
((SslHandshakeCompletionEvent) evt).cause() != null) {
Throwable cause = ((SslHandshakeCompletionEvent) evt).cause();
cause.printStackTrace();
error.set(cause);
}
ctx.fireUserEventTriggered(evt);
}
});
}
})
.connect(sc.localAddress())
.addListener((ChannelFutureListener) future ->
future.channel().writeAndFlush(wrappedBuffer(new byte [] { 1, 2, 3, 4 })))
.syncUninterruptibly()
.channel();
assertTrue(activeLatch.await(5, TimeUnit.SECONDS));
assertNull(error.get());
} finally {
if (cc != null) {
cc.close().syncUninterruptibly();
}
if (sc != null) {
sc.close().syncUninterruptibly();
}
group.shutdownGracefully();
ReferenceCountUtil.release(sslClientCtx);
}
}
private static void testTrustManagerVerify(String tlsVersion) throws Exception {
final SslContext sslClientCtx =
SslContextBuilder.forClient()