diff --git a/src/main/java/org/apache/hadoop/hbase/thrift/TBoundedThreadPoolServer.java b/src/main/java/org/apache/hadoop/hbase/thrift/TBoundedThreadPoolServer.java index c7e104b..dd79aca 100644 --- a/src/main/java/org/apache/hadoop/hbase/thrift/TBoundedThreadPoolServer.java +++ b/src/main/java/org/apache/hadoop/hbase/thrift/TBoundedThreadPoolServer.java @@ -284,7 +284,15 @@ public class TBoundedThreadPoolServer extends TServer { outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); // we check stopped_ first to make sure we're not supposed to be shutting // down. this is necessary for graceful shutdown. - while (!stopped && processor.process(inputProtocol, outputProtocol)) {} + while (!stopped && processor.process(inputProtocol, outputProtocol)) { + // message limit is reset for every request + // see THRIFT-601, working on thrift 0.8.0 + // NOTE that THRIFT-820 breaks this again in thrift 0.9.0 + // and TFramedTransport needs to be used from this version onwards + // to avoid the buffer overflow + inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); + } } catch (TTransportException ttx) { // Assume the client died and continue silently } catch (TException tx) { diff --git a/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java b/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java index 4aaa565..f8317d3 100644 --- a/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java +++ b/src/main/java/org/apache/hadoop/hbase/thrift/ThriftServerRunner.java @@ -115,6 +115,9 @@ public class ThriftServerRunner implements Runnable { static final String COMPACT_CONF_KEY = "hbase.regionserver.thrift.compact"; static final String FRAMED_CONF_KEY = "hbase.regionserver.thrift.framed"; static final String PORT_CONF_KEY = "hbase.regionserver.thrift.port"; + //The max length of an individual thrift message and frames in MB + static final String MAX_MESSAGE_LENGTH_CONF_KEY = "hbase.regionserver.thrift.binary.max_message_length_in_mb"; + static final String MAX_FRAME_SIZE_CONF_KEY = "hbase.regionserver.thrift.framed.max_frame_size_in_mb"; static final String COALESCE_INC_KEY = "hbase.regionserver.thrift.coalesceIncrement"; private static final String DEFAULT_BIND_ADDR = "0.0.0.0"; @@ -269,7 +272,8 @@ public class ThriftServerRunner implements Runnable { protocolFactory = new TCompactProtocol.Factory(); } else { LOG.debug("Using binary protocol"); - protocolFactory = new TBinaryProtocol.Factory(); + int maxMessageLength = conf.getInt(MAX_MESSAGE_LENGTH_CONF_KEY, 2) * 1024 * 1024; + protocolFactory = new TBinaryProtocol.Factory(false, true, maxMessageLength); } Hbase.Processor processor = @@ -279,7 +283,8 @@ public class ThriftServerRunner implements Runnable { // Construct correct TransportFactory TTransportFactory transportFactory; if (conf.getBoolean(FRAMED_CONF_KEY, false) || implType.isAlwaysFramed) { - transportFactory = new TFramedTransport.Factory(); + int maxFrameSize = conf.getInt(MAX_FRAME_SIZE_CONF_KEY, 2) * 1024 * 1024; + transportFactory = new TFramedTransport.Factory(maxFrameSize); LOG.debug("Using framed transport"); } else { transportFactory = new TTransportFactory(); diff --git a/src/main/java/org/apache/hadoop/hbase/thrift2/ThriftServer.java b/src/main/java/org/apache/hadoop/hbase/thrift2/ThriftServer.java index b6235ac..e2831f7 100644 --- a/src/main/java/org/apache/hadoop/hbase/thrift2/ThriftServer.java +++ b/src/main/java/org/apache/hadoop/hbase/thrift2/ThriftServer.java @@ -74,6 +74,8 @@ public class ThriftServer { private static final Log log = LogFactory.getLog(ThriftServer.class); public static final String DEFAULT_LISTEN_PORT = "9090"; + //The max length of a message frame in MB + static final String MAX_FRAME_SIZE_CONF_KEY = "hbase.regionserver.thrift.framed.max_frame_size_in_mb"; public ThriftServer() { } @@ -124,10 +126,10 @@ public class ThriftServer { } } - private static TTransportFactory getTTransportFactory(boolean framed) { + private static TTransportFactory getTTransportFactory(boolean framed, int maxFrameSize) { if (framed) { log.debug("Using framed transport"); - return new TFramedTransport.Factory(); + return new TFramedTransport.Factory(maxFrameSize); } else { return new TTransportFactory(); } @@ -275,7 +277,8 @@ public class ThriftServer { boolean framed = cmd.hasOption("framed") || conf.getBoolean("hbase.regionserver.thrift.framed", false) || nonblocking || hsha; - TTransportFactory transportFactory = getTTransportFactory(framed); + TTransportFactory transportFactory = getTTransportFactory(framed, + conf.getInt(MAX_FRAME_SIZE_CONF_KEY, 2) * 1024 * 1024); conf.setBoolean("hbase.regionserver.thrift.framed", framed); // TODO: Remove once HBASE-2155 is resolved diff --git a/src/main/resources/hbase-default.xml b/src/main/resources/hbase-default.xml index 12e19e4..e6ed69a 100644 --- a/src/main/resources/hbase-default.xml +++ b/src/main/resources/hbase-default.xml @@ -888,6 +888,26 @@ + hbase.regionserver.thrift.framed + false + Use Thrift TFramedTransport on the server side. + This is the recommended transport for thrift servers and requires a similar setting + on the client side. + Setting this to false will select the default transport, + vulnerable to DoS when malformed requests are issued due to THRIFT-601. + + + + hbase.regionserver.thrift.framed.max_frame_size_in_mb + 2 + Default frame size when using framed transport + + + hbase.regionserver.thrift.compact + false + Use Thrift TCompactProtocol binary serialization protocol. + + hbase.thrift.minWorkerThreads 16