Skip to content
Open
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
18 changes: 15 additions & 3 deletions hadoop-hdds/common/src/main/java/org/apache/hadoop/ipc_/RPC.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public class RPC {
final static int RPC_SERVICE_CLASS_DEFAULT = 0;
public enum RpcKind {
RPC_BUILTIN ((short) 1), // Used for built in calls by tests
RPC_WRITABLE ((short) 2), // Use WritableRpcEngine
RPC_WRITABLE ((short) 2), // ignored
RPC_PROTOCOL_BUFFER ((short) 3); // Use ProtobufRpcEngine
final static short MAX_SIZE = RPC_PROTOCOL_BUFFER.value; // used for array size
private final short value;
Expand Down Expand Up @@ -216,8 +216,7 @@ static synchronized RpcEngine getProtocolEngine(Class<?> protocol,
Configuration conf) {
RpcEngine engine = PROTOCOL_ENGINES.get(protocol);
if (engine == null) {
Class<?> impl = conf.getClass(ENGINE_PROP+"."+protocol.getName(),
WritableRpcEngine.class);
Class<?> impl = conf.getClass(ENGINE_PROP+"."+protocol.getName(), ProtobufRpcEngine.class);
engine = (RpcEngine)ReflectionUtils.newInstance(impl, conf);
PROTOCOL_ENGINES.put(protocol, engine);
}
Expand Down Expand Up @@ -1034,6 +1033,19 @@ Map<ProtoNameVer, ProtoClassProtoImpl> getProtocolImplMap(RPC.RpcKind rpcKind) {
return protocolImplMapArray.get(rpcKind.ordinal());
}

/**
* Returns {@code true} only if at least one protocol has been registered
* on this server instance for the given {@link RPC.RpcKind}.
* Used to reject incoming requests for unsupported RPC kinds before any
* deserialization of the request payload takes place.
* @param rpcKind the RPC kind from the incoming request header.
* @return {@code true} if at least one protocol is registered for this kind.
*/
boolean hasRegisteredProtocols(RPC.RpcKind rpcKind) {
Map<ProtoNameVer, ProtoClassProtoImpl> implMap = getProtocolImplMap(rpcKind);
return implMap != null && !implMap.isEmpty();
}

// Register protocol and its impl for rpc calls
void registerProtocolAndImpl(RpcKind rpcKind, Class<?> protocolClass,
Object protocolImpl) {
Expand Down
40 changes: 29 additions & 11 deletions hadoop-hdds/common/src/main/java/org/apache/hadoop/ipc_/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -2654,28 +2654,46 @@ private void checkRpcHeaders(RpcRequestHeaderProto header)
private void processRpcRequest(RpcRequestHeaderProto header,
RpcWritable.Buffer buffer) throws RpcServerException,
InterruptedException {
Class<? extends Writable> rpcRequestClass =
if (header.getRpcKind() == RpcKindProto.RPC_WRITABLE) {
final String err = "WritableRpcEngine is not supported.";
LOG.warn("{} Client: {}", err, getHostAddress());
throw new FatalRpcServerException(RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER, err);
}
// Reject requests for RPC kinds with no registered protocols on this
// server instance. This prevents deserialization of untrusted payloads
// for unsupported kinds. See HADOOP-19864.
if (Server.this instanceof RPC.Server) {
RPC.Server server = (RPC.Server) Server.this;
final RPC.RpcKind kind = ProtoUtil.convert(header.getRpcKind());
if (!server.hasRegisteredProtocols(kind)) {
final String err = "No protocols registered on this server for RpcKind "
+ header.getRpcKind()
+ ". Rejecting request without deserialization.";
LOG.info("{} Client: {}", err, getHostAddress());
throw new FatalRpcServerException(
RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER, err);
}
}
Class<? extends Writable> rpcRequestClass =
getRpcRequestWrapper(header.getRpcKind());
if (rpcRequestClass == null) {
LOG.warn("Unknown rpc kind " + header.getRpcKind() +
" from client " + getHostAddress());
final String err = "Unknown rpc kind in rpc header" +
header.getRpcKind();
LOG.warn("Unknown rpc kind {} from client {}", header.getRpcKind(), getHostAddress());
throw new FatalRpcServerException(
RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER, err);
RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER,
"Unknown rpc kind in rpc header " + header.getRpcKind());
}
Writable rpcRequest;
try { //Read the rpc request
rpcRequest = buffer.newInstance(rpcRequestClass, conf);
} catch (RpcServerException rse) { // lets tests inject failures.
throw rse;
} catch (Throwable t) { // includes runtime exception from newInstance
LOG.warn("Unable to read call parameters for client " +
getHostAddress() + "on connection protocol " +
this.protocolName + " for rpcKind " + header.getRpcKind(), t);
String err = "IPC server unable to read call parameters: "+ t.getMessage();
LOG.warn(
"Unable to read call parameters for client {} on connection protocol {} for rpcKind {}",
getHostAddress(), this.protocolName, header.getRpcKind(), t);
throw new FatalRpcServerException(
RpcErrorCodeProto.FATAL_DESERIALIZING_REQUEST, err);
RpcErrorCodeProto.FATAL_DESERIALIZING_REQUEST,
"IPC server unable to read call parameters: "+ t.getMessage());
}

CallerContext callerContext = null;
Expand Down
Loading