Allow blocking calls in UnixResolverDnsServerAddressStreamProvider#parse (#10935)

Motivation:

Internally UnixResolverDnsServerAddressStreamProvider#parse calls FileInputStream.read(...)
when parsing the etcResolverFiles.
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 #10925
This commit is contained in:
Violeta Georgieva 2021-01-14 19:27:12 +02:00 committed by GitHub
parent c509a477ef
commit 5b699b722c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 0 deletions

View File

@ -115,6 +115,10 @@ class Hidden {
"sun.security.ssl.SSLEngineImpl", "sun.security.ssl.SSLEngineImpl",
"wrap"); "wrap");
builder.allowBlockingCallsInside(
"io.netty.resolver.dns.UnixResolverDnsServerAddressStreamProvider",
"parse");
builder.nonBlockingThreadPredicate(new Function<Predicate<Thread>, Predicate<Thread>>() { builder.nonBlockingThreadPredicate(new Function<Predicate<Thread>, Predicate<Thread>>() {
@Override @Override
public Predicate<Thread> apply(final Predicate<Thread> p) { public Predicate<Thread> apply(final Predicate<Thread> p) {

View File

@ -89,6 +89,11 @@
<artifactId>netty-handler</artifactId> <artifactId>netty-handler</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-resolver-dns</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>${tcnative.artifactId}</artifactId> <artifactId>${tcnative.artifactId}</artifactId>

View File

@ -35,6 +35,8 @@ import io.netty.handler.ssl.SslHandshakeCompletionEvent;
import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.resolver.dns.DnsServerAddressStreamProvider;
import io.netty.resolver.dns.DnsServerAddressStreamProviders;
import io.netty.util.HashedWheelTimer; import io.netty.util.HashedWheelTimer;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.concurrent.DefaultThreadFactory;
@ -53,6 +55,8 @@ import reactor.blockhound.BlockingOperationError;
import reactor.blockhound.integration.BlockHoundIntegration; import reactor.blockhound.integration.BlockHoundIntegration;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -69,6 +73,7 @@ import java.util.concurrent.locks.ReentrantLock;
import static io.netty.buffer.Unpooled.wrappedBuffer; import static io.netty.buffer.Unpooled.wrappedBuffer;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -314,6 +319,40 @@ public class NettyBlockHoundIntegrationTest {
} }
} }
@Test(timeout = 5000L)
public void testParseEtcResolverFilesAllowsBlockingCalls() throws InterruptedException {
SingleThreadEventExecutor executor =
new SingleThreadEventExecutor(null, new DefaultThreadFactory("test"), true) {
@Override
protected void run() {
while (!confirmShutdown()) {
Runnable task = takeTask();
if (task != null) {
task.run();
}
}
}
};
try {
CountDownLatch latch = new CountDownLatch(1);
List<DnsServerAddressStreamProvider> result = new ArrayList<>();
List<Throwable> error = new ArrayList<>();
executor.execute(() -> {
try {
result.add(DnsServerAddressStreamProviders.unixDefault());
} catch (Throwable t) {
error.add(t);
}
latch.countDown();
});
latch.await();
assertEquals(0, error.size());
assertEquals(1, result.size());
} finally {
executor.shutdownGracefully();
}
}
private static void testTrustManagerVerify(String tlsVersion) throws Exception { private static void testTrustManagerVerify(String tlsVersion) throws Exception {
final SslContext sslClientCtx = final SslContext sslClientCtx =
SslContextBuilder.forClient() SslContextBuilder.forClient()