Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
Expand Down Expand Up @@ -580,6 +582,16 @@ public interface EntitlementChecker {
* (not instrumentable).
*/

void check$java_nio_channels_spi_AbstractSelectableChannel$register(
Class<?> callerClass,
SelectableChannel that,
Selector sel,
int ops,
Object att
);

void check$java_nio_channels_SelectableChannel$register(Class<?> callerClass, SelectableChannel that, Selector sel, int ops);

// bind

void check$java_nio_channels_AsynchronousServerSocketChannel$bind(
Expand All @@ -603,6 +615,12 @@ public interface EntitlementChecker {

void check$sun_nio_ch_ServerSocketChannelImpl$bind(Class<?> callerClass, ServerSocketChannel that, SocketAddress local, int backlog);

void check$java_nio_channels_SocketChannel$$open(Class<?> callerClass);

void check$java_nio_channels_SocketChannel$$open(Class<?> callerClass, java.net.ProtocolFamily family);

void check$java_nio_channels_SocketChannel$$open(Class<?> callerClass, SocketAddress remote);

void check$sun_nio_ch_SocketChannelImpl$bind(Class<?> callerClass, SocketChannel that, SocketAddress local);

// connect
Expand Down Expand Up @@ -650,6 +668,18 @@ public interface EntitlementChecker {
// provider methods (dynamic)
void checkSelectorProviderInheritedChannel(Class<?> callerClass, SelectorProvider that);

void checkSelectorProviderOpenDatagramChannel(Class<?> callerClass, SelectorProvider that);

void checkSelectorProviderOpenDatagramChannel(Class<?> callerClass, SelectorProvider that, java.net.ProtocolFamily family);

void checkSelectorProviderOpenServerSocketChannel(Class<?> callerClass, SelectorProvider that);

void checkSelectorProviderOpenServerSocketChannel(Class<?> callerClass, SelectorProvider that, java.net.ProtocolFamily family);

void checkSelectorProviderOpenSocketChannel(Class<?> callerClass, SelectorProvider that);

void checkSelectorProviderOpenSocketChannel(Class<?> callerClass, SelectorProvider that, java.net.ProtocolFamily family);

/// /////////////////
//
// Load native libraries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.elasticsearch.core.SuppressForbidden;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
Expand Down Expand Up @@ -41,9 +42,12 @@
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.AbstractSelector;
import java.nio.channels.spi.AsynchronousChannelProvider;
import java.nio.channels.spi.SelectorProvider;
Expand Down Expand Up @@ -846,4 +850,71 @@ public void implCloseChannel(SelectableChannel sc) {}
@Override
public void implReleaseChannel(SelectableChannel sc) {}
}

static class DummySelectableChannel extends AbstractSelectableChannel {
protected DummySelectableChannel(SelectorProvider provider) {
super(provider);
}

@Override
protected void implCloseSelectableChannel() throws IOException {

}

@Override
protected void implConfigureBlocking(boolean block) throws IOException {

}

@Override
public int validOps() {
return SelectionKey.OP_ACCEPT | SelectionKey.OP_CONNECT;
}
}

static class DummySelector extends AbstractSelector {
protected DummySelector(SelectorProvider provider) {
super(provider);
}

@Override
protected void implCloseSelector() throws IOException {

}

@Override
protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att) {
return null;
}

@Override
public Set<SelectionKey> keys() {
return Set.of();
}

@Override
public Set<SelectionKey> selectedKeys() {
return Set.of();
}

@Override
public int selectNow() throws IOException {
return 0;
}

@Override
public int select(long timeout) throws IOException {
return 0;
}

@Override
public int select() throws IOException {
return 0;
}

@Override
public Selector wakeup() {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.StandardProtocolFamily;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
Expand Down Expand Up @@ -203,6 +204,20 @@ static void socketChannelConnect() throws IOException {
}
}

@EntitlementTest(expectedAccess = PLUGINS)
static void socketChannelOpenProtocol() throws IOException {
SocketChannel.open(StandardProtocolFamily.INET).close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void socketChannelOpenAddress() throws IOException {
try {
SocketChannel.open(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)).close();
} catch (SocketException ex) {
// Some sort of SocketException is expected, we are trying to connect to port 0
}
}

@EntitlementTest(expectedAccess = PLUGINS)
static void asynchronousSocketChannelBind() throws IOException {
try (var socketChannel = AsynchronousSocketChannel.open()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@

import java.io.FileDescriptor;
import java.io.IOException;
import java.net.StandardProtocolFamily;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.SelectorProvider;
import java.nio.file.StandardOpenOption;
import java.util.Set;

Expand Down Expand Up @@ -85,4 +88,50 @@ static void asynchronousFileChannelOpenForReadWithOptions() throws IOException {
static void channelsReadWriteSelectableChannel() throws IOException {
jdk.nio.Channels.readWriteSelectableChannel(new FileDescriptor(), new DummyImplementations.DummySelectableChannelCloser()).close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectableChannelRegisterConnect() throws IOException {
try (var selectableChannel = new DummyImplementations.DummySelectableChannel(SelectorProvider.provider())) {
selectableChannel.configureBlocking(false);
selectableChannel.register(new DummyImplementations.DummySelector(SelectorProvider.provider()), SelectionKey.OP_CONNECT);
}
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectableChannelRegisterAccept() throws IOException {
try (var selectableChannel = new DummyImplementations.DummySelectableChannel(SelectorProvider.provider())) {
selectableChannel.configureBlocking(false);
selectableChannel.register(new DummyImplementations.DummySelector(SelectorProvider.provider()), SelectionKey.OP_ACCEPT);
}
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenSocketChannel() throws IOException {
SelectorProvider.provider().openSocketChannel().close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenDatagramChannel() throws IOException {
SelectorProvider.provider().openDatagramChannel().close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenServerSocketChannel() throws IOException {
SelectorProvider.provider().openServerSocketChannel().close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenSocketChannelWithProtocol() throws IOException {
SelectorProvider.provider().openSocketChannel(StandardProtocolFamily.INET).close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenDatagramChannelWithProtocol() throws IOException {
SelectorProvider.provider().openDatagramChannel(StandardProtocolFamily.INET).close();
}

@EntitlementTest(expectedAccess = PLUGINS)
static void selectorProviderOpenServerSocketChannelWithProtocol() throws IOException {
SelectorProvider.provider().openServerSocketChannel(StandardProtocolFamily.INET).close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,20 +122,7 @@ static void initialize(Instrumentation inst, Class<?> checkerInterface, boolean
private static Map<MethodKey, CheckMethod> getMethodsToInstrument(Class<?> checkerInterface) throws ClassNotFoundException,
NoSuchMethodException {
Map<MethodKey, CheckMethod> checkMethods = new HashMap<>(INSTRUMENTATION_SERVICE.lookupMethods(checkerInterface));
Stream.of(
fileSystemProviderChecks(),
fileStoreChecks(),
pathChecks(),
Stream.of(
INSTRUMENTATION_SERVICE.lookupImplementationMethod(
SelectorProvider.class,
"inheritedChannel",
SelectorProvider.provider().getClass(),
EntitlementChecker.class,
"checkSelectorProviderInheritedChannel"
)
)
)
Stream.of(fileSystemProviderChecks(), fileStoreChecks(), pathChecks(), selectorProviderChecks())
.flatMap(Function.identity())
.forEach(instrumentation -> checkMethods.put(instrumentation.targetMethod(), instrumentation.checkMethod()));

Expand Down Expand Up @@ -282,6 +269,39 @@ private static Stream<InstrumentationService.InstrumentationInfo> pathChecks() {
});
}

private static Stream<InstrumentationService.InstrumentationInfo> selectorProviderChecks() {
var selectorProviderClass = SelectorProvider.provider().getClass();

var instrumentation = new InstrumentationInfoFactory() {
@Override
public InstrumentationService.InstrumentationInfo of(String methodName, Class<?>... parameterTypes)
throws ClassNotFoundException, NoSuchMethodException {
return INSTRUMENTATION_SERVICE.lookupImplementationMethod(
SelectorProvider.class,
methodName,
selectorProviderClass,
EntitlementChecker.class,
"checkSelectorProvider" + Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1),
parameterTypes
);
}
};

try {
return Stream.of(
instrumentation.of("inheritedChannel"),
instrumentation.of("openDatagramChannel"),
instrumentation.of("openDatagramChannel", java.net.ProtocolFamily.class),
instrumentation.of("openServerSocketChannel"),
instrumentation.of("openServerSocketChannel", java.net.ProtocolFamily.class),
instrumentation.of("openSocketChannel"),
instrumentation.of("openSocketChannel", java.net.ProtocolFamily.class)
);
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}

private static Class<?>[] findClassesToRetransform(Class<?>[] loadedClasses, Set<String> classesToTransform) {
List<Class<?>> retransform = new ArrayList<>();
for (Class<?> loadedClass : loadedClasses) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ private static void ensureClassesSensitiveToVerificationAreInitialized() {
var classesToInitialize = Set.of(
"sun.net.www.protocol.http.HttpURLConnection",
"sun.nio.ch.SocketChannelImpl",
"java.net.ProxySelector"
"java.net.ProxySelector",
"sun.nio.ch.DatagramChannelImpl",
"sun.nio.ch.ServerSocketChannelImpl"
);
for (String className : classesToInitialize) {
try {
Expand Down
Loading