tomcat/CVE-2019-0199-5.patch
2020-02-28 20:54:21 -05:00

144 lines
4.9 KiB
Diff

--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701
+++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:22 1852702
@@ -54,6 +54,8 @@
// This default is defined by the HTTP/2 specification
static final int DEFAULT_INITIAL_WINDOW_SIZE = (1 << 16) - 1;
+ static final int DEFAULT_OVERHEAD_COUNT_FACTOR = 1;
+
private static final String HTTP_UPGRADE_NAME = "h2c";
private static final String ALPN_NAME = "h2";
private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8);
@@ -79,6 +81,8 @@
private int maxHeaderSize = Constants.DEFAULT_MAX_HEADER_SIZE;
private int maxTrailerCount = Constants.DEFAULT_MAX_TRAILER_COUNT;
private int maxTrailerSize = Constants.DEFAULT_MAX_TRAILER_SIZE;
+ private int overheadCountFactor = DEFAULT_OVERHEAD_COUNT_FACTOR;
+
private boolean initiatePingDisabled = false;
private boolean useSendfile = true;
// Compression
@@ -306,6 +310,16 @@
}
+ public int getOverheadCountFactor() {
+ return overheadCountFactor;
+ }
+
+
+ public void setOverheadCountFactor(int overheadCountFactor) {
+ this.overheadCountFactor = overheadCountFactor;
+ }
+
+
public void setInitiatePingDisabled(boolean initiatePingDisabled) {
this.initiatePingDisabled = initiatePingDisabled;
}
--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701
+++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:22 1852702
@@ -30,6 +30,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.WebConnection;
@@ -139,6 +140,9 @@
private AtomicInteger streamConcurrency = null;
private Queue<StreamRunnable> queuedRunnable = null;
+ // Track 'overhead' frames vs 'request/response' frames
+ private final AtomicLong overheadCount = new AtomicLong(-10);
+
Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest) {
super (STREAM_ID_ZERO);
@@ -330,6 +334,10 @@
}
}
+ if (overheadCount.get() > 0) {
+ throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM);
+ }
+
if (activeRemoteStreamCount.get() == 0) {
// No streams currently active. Use the keep-alive
// timeout for the connection.
@@ -638,6 +646,9 @@
log.debug(sm.getString("upgradeHandler.writeBody", connectionId, stream.getIdentifier(),
Integer.toString(len)));
}
+
+ reduceOverheadCount();
+
// Need to check this now since sending end of stream will change this.
boolean writeable = stream.canWrite();
byte[] header = new byte[9];
@@ -1193,6 +1204,16 @@
}
+ private void reduceOverheadCount() {
+ overheadCount.decrementAndGet();
+ }
+
+
+ private void increaseOverheadCount() {
+ overheadCount.addAndGet(getProtocol().getOverheadCountFactor());
+ }
+
+
// ----------------------------------------------- Http2Parser.Input methods
@Override
@@ -1247,6 +1268,7 @@
@Override
public ByteBuffer startRequestBodyFrame(int streamId, int payloadSize) throws Http2Exception {
+ reduceOverheadCount();
Stream stream = getStream(streamId, true);
stream.checkState(FrameType.DATA);
stream.receivedData(payloadSize);
@@ -1291,6 +1313,8 @@
// determines if a new stream is created or if this stream is ignored.
checkPauseState();
+ reduceOverheadCount();
+
if (connectionState.get().isNewStreamAllowed()) {
Stream stream = getStream(streamId, false);
if (stream == null) {
@@ -1340,6 +1364,9 @@
throw new ConnectionException(sm.getString("upgradeHandler.dependency.invalid",
getConnectionId(), Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR);
}
+
+ increaseOverheadCount();
+
Stream stream = getStream(streamId, false);
if (stream == null) {
stream = createRemoteStream(streamId);
@@ -1384,6 +1411,9 @@
@Override
public void setting(Setting setting, long value) throws ConnectionException {
+
+ increaseOverheadCount();
+
// Special handling required
if (setting == Setting.INITIAL_WINDOW_SIZE) {
long oldValue = remoteSettings.getInitialWindowSize();
@@ -1425,6 +1455,9 @@
@Override
public void pingReceive(byte[] payload, boolean ack) throws IOException {
+ if (!ack) {
+ increaseOverheadCount();
+ }
pingManager.receivePing(payload, ack);
}