Wrap netty accept/connect ops with doPrivileged (#22572)
This is related to #22116. netty channels require socket `connect` and `accept` privileges. Netty does not currently wrap these operations with `doPrivileged` blocks. These changes extend the netty channels and wrap calls to the relevant super methods in doPrivileged blocks.
This commit is contained in:
parent
cd236c4de4
commit
f4270f9914
|
@ -33,8 +33,6 @@ import io.netty.channel.FixedRecvByteBufAllocator;
|
||||||
import io.netty.channel.RecvByteBufAllocator;
|
import io.netty.channel.RecvByteBufAllocator;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.oio.OioEventLoopGroup;
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
import io.netty.handler.codec.http.HttpContentCompressor;
|
import io.netty.handler.codec.http.HttpContentCompressor;
|
||||||
import io.netty.handler.codec.http.HttpContentDecompressor;
|
import io.netty.handler.codec.http.HttpContentDecompressor;
|
||||||
|
@ -80,6 +78,8 @@ import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.transport.BindTransportException;
|
import org.elasticsearch.transport.BindTransportException;
|
||||||
import org.elasticsearch.transport.netty4.Netty4OpenChannelsHandler;
|
import org.elasticsearch.transport.netty4.Netty4OpenChannelsHandler;
|
||||||
import org.elasticsearch.transport.netty4.Netty4Utils;
|
import org.elasticsearch.transport.netty4.Netty4Utils;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedNioServerSocketChannel;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedOioServerSocketChannel;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
@ -301,11 +301,11 @@ public class Netty4HttpServerTransport extends AbstractLifecycleComponent implem
|
||||||
if (blockingServer) {
|
if (blockingServer) {
|
||||||
serverBootstrap.group(new OioEventLoopGroup(workerCount, daemonThreadFactory(settings,
|
serverBootstrap.group(new OioEventLoopGroup(workerCount, daemonThreadFactory(settings,
|
||||||
HTTP_SERVER_WORKER_THREAD_NAME_PREFIX)));
|
HTTP_SERVER_WORKER_THREAD_NAME_PREFIX)));
|
||||||
serverBootstrap.channel(OioServerSocketChannel.class);
|
serverBootstrap.channel(PrivilegedOioServerSocketChannel.class);
|
||||||
} else {
|
} else {
|
||||||
serverBootstrap.group(new NioEventLoopGroup(workerCount, daemonThreadFactory(settings,
|
serverBootstrap.group(new NioEventLoopGroup(workerCount, daemonThreadFactory(settings,
|
||||||
HTTP_SERVER_WORKER_THREAD_NAME_PREFIX)));
|
HTTP_SERVER_WORKER_THREAD_NAME_PREFIX)));
|
||||||
serverBootstrap.channel(NioServerSocketChannel.class);
|
serverBootstrap.channel(PrivilegedNioServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverBootstrap.childHandler(configureServerChannelHandler());
|
serverBootstrap.childHandler(configureServerChannelHandler());
|
||||||
|
|
|
@ -33,10 +33,6 @@ import io.netty.channel.FixedRecvByteBufAllocator;
|
||||||
import io.netty.channel.RecvByteBufAllocator;
|
import io.netty.channel.RecvByteBufAllocator;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.oio.OioEventLoopGroup;
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
|
||||||
import io.netty.channel.socket.oio.OioSocketChannel;
|
|
||||||
import io.netty.util.concurrent.Future;
|
import io.netty.util.concurrent.Future;
|
||||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||||
import org.apache.logging.log4j.util.Supplier;
|
import org.apache.logging.log4j.util.Supplier;
|
||||||
|
@ -67,6 +63,10 @@ import org.elasticsearch.transport.TcpTransport;
|
||||||
import org.elasticsearch.transport.TransportRequestOptions;
|
import org.elasticsearch.transport.TransportRequestOptions;
|
||||||
import org.elasticsearch.transport.TransportServiceAdapter;
|
import org.elasticsearch.transport.TransportServiceAdapter;
|
||||||
import org.elasticsearch.transport.TransportSettings;
|
import org.elasticsearch.transport.TransportSettings;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedNioServerSocketChannel;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedNioSocketChannel;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedOioServerSocketChannel;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedOioSocketChannel;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -195,10 +195,10 @@ public class Netty4Transport extends TcpTransport<Channel> {
|
||||||
final Bootstrap bootstrap = new Bootstrap();
|
final Bootstrap bootstrap = new Bootstrap();
|
||||||
if (TCP_BLOCKING_CLIENT.get(settings)) {
|
if (TCP_BLOCKING_CLIENT.get(settings)) {
|
||||||
bootstrap.group(new OioEventLoopGroup(1, daemonThreadFactory(settings, TRANSPORT_CLIENT_WORKER_THREAD_NAME_PREFIX)));
|
bootstrap.group(new OioEventLoopGroup(1, daemonThreadFactory(settings, TRANSPORT_CLIENT_WORKER_THREAD_NAME_PREFIX)));
|
||||||
bootstrap.channel(OioSocketChannel.class);
|
bootstrap.channel(PrivilegedOioSocketChannel.class);
|
||||||
} else {
|
} else {
|
||||||
bootstrap.group(new NioEventLoopGroup(workerCount, daemonThreadFactory(settings, TRANSPORT_CLIENT_BOSS_THREAD_NAME_PREFIX)));
|
bootstrap.group(new NioEventLoopGroup(workerCount, daemonThreadFactory(settings, TRANSPORT_CLIENT_BOSS_THREAD_NAME_PREFIX)));
|
||||||
bootstrap.channel(NioSocketChannel.class);
|
bootstrap.channel(PrivilegedNioSocketChannel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrap.handler(getClientChannelInitializer());
|
bootstrap.handler(getClientChannelInitializer());
|
||||||
|
@ -284,10 +284,10 @@ public class Netty4Transport extends TcpTransport<Channel> {
|
||||||
|
|
||||||
if (TCP_BLOCKING_SERVER.get(settings)) {
|
if (TCP_BLOCKING_SERVER.get(settings)) {
|
||||||
serverBootstrap.group(new OioEventLoopGroup(workerCount, workerFactory));
|
serverBootstrap.group(new OioEventLoopGroup(workerCount, workerFactory));
|
||||||
serverBootstrap.channel(OioServerSocketChannel.class);
|
serverBootstrap.channel(PrivilegedOioServerSocketChannel.class);
|
||||||
} else {
|
} else {
|
||||||
serverBootstrap.group(new NioEventLoopGroup(workerCount, workerFactory));
|
serverBootstrap.group(new NioEventLoopGroup(workerCount, workerFactory));
|
||||||
serverBootstrap.channel(NioServerSocketChannel.class);
|
serverBootstrap.channel(PrivilegedNioServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverBootstrap.childHandler(getServerChannelInitializer(name, settings));
|
serverBootstrap.childHandler(getServerChannelInitializer(name, settings));
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.transport.netty4.channel;
|
||||||
|
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import org.elasticsearch.SpecialPermission;
|
||||||
|
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps netty calls to {@link java.nio.channels.ServerSocketChannel#accept()} in
|
||||||
|
* {@link AccessController#doPrivileged(PrivilegedAction)} blocks. This is necessary to limit
|
||||||
|
* {@link java.net.SocketPermission} to the transport module.
|
||||||
|
*/
|
||||||
|
public class PrivilegedNioServerSocketChannel extends NioServerSocketChannel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int doReadMessages(List<Object> buf) throws Exception {
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null) {
|
||||||
|
sm.checkPermission(new SpecialPermission());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return AccessController.doPrivileged((PrivilegedExceptionAction<Integer>) () -> super.doReadMessages(buf));
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw (Exception) e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.transport.netty4.channel;
|
||||||
|
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import org.elasticsearch.SpecialPermission;
|
||||||
|
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps netty calls to {@link java.nio.channels.SocketChannel#connect(SocketAddress)} in
|
||||||
|
* {@link AccessController#doPrivileged(PrivilegedAction)} blocks. This is necessary to limit
|
||||||
|
* {@link java.net.SocketPermission} to the transport module.
|
||||||
|
*/
|
||||||
|
public class PrivilegedNioSocketChannel extends NioSocketChannel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null) {
|
||||||
|
sm.checkPermission(new SpecialPermission());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () -> super.doConnect(remoteAddress, localAddress));
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw (Exception) e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.transport.netty4.channel;
|
||||||
|
|
||||||
|
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
||||||
|
import org.elasticsearch.SpecialPermission;
|
||||||
|
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps netty calls to {@link ServerSocket#accept()} in {@link AccessController#doPrivileged(PrivilegedAction)} blocks.
|
||||||
|
* This is necessary to limit {@link java.net.SocketPermission} to the transport module.
|
||||||
|
*/
|
||||||
|
public class PrivilegedOioServerSocketChannel extends OioServerSocketChannel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int doReadMessages(List<Object> buf) throws Exception {
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null) {
|
||||||
|
sm.checkPermission(new SpecialPermission());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return AccessController.doPrivileged((PrivilegedExceptionAction<Integer>) () -> super.doReadMessages(buf));
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw (Exception) e.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.transport.netty4.channel;
|
||||||
|
|
||||||
|
import io.netty.channel.socket.oio.OioSocketChannel;
|
||||||
|
import org.elasticsearch.SpecialPermission;
|
||||||
|
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.security.PrivilegedActionException;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps netty calls to {@link java.net.Socket#connect(SocketAddress)} in
|
||||||
|
* {@link AccessController#doPrivileged(PrivilegedAction)} blocks. This is necessary to limit
|
||||||
|
* {@link java.net.SocketPermission} to the transport module.
|
||||||
|
*/
|
||||||
|
public class PrivilegedOioSocketChannel extends OioSocketChannel {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
|
||||||
|
SecurityManager sm = System.getSecurityManager();
|
||||||
|
if (sm != null) {
|
||||||
|
sm.checkPermission(new SpecialPermission());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||||
|
super.doConnect(remoteAddress, localAddress);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
} catch (PrivilegedActionException e) {
|
||||||
|
throw (Exception) e.getCause();
|
||||||
|
}
|
||||||
|
super.doConnect(remoteAddress, localAddress);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
|
||||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpRequest;
|
import io.netty.handler.codec.http.FullHttpRequest;
|
||||||
import io.netty.handler.codec.http.FullHttpResponse;
|
import io.netty.handler.codec.http.FullHttpResponse;
|
||||||
|
@ -44,6 +43,7 @@ import io.netty.handler.codec.http.HttpVersion;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
|
import org.elasticsearch.transport.netty4.channel.PrivilegedNioSocketChannel;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
@ -82,7 +82,7 @@ class Netty4HttpClient implements Closeable {
|
||||||
private final Bootstrap clientBootstrap;
|
private final Bootstrap clientBootstrap;
|
||||||
|
|
||||||
Netty4HttpClient() {
|
Netty4HttpClient() {
|
||||||
clientBootstrap = new Bootstrap().channel(NioSocketChannel.class).group(new NioEventLoopGroup());
|
clientBootstrap = new Bootstrap().channel(PrivilegedNioSocketChannel.class).group(new NioEventLoopGroup());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<FullHttpResponse> get(SocketAddress remoteAddress, String... uris) throws InterruptedException {
|
public Collection<FullHttpResponse> get(SocketAddress remoteAddress, String... uris) throws InterruptedException {
|
||||||
|
|
Loading…
Reference in New Issue