[Git][java-team/jetty9][bookworm] Import Debian changes 9.4.50-4+deb12u2
Markus Koschany (@apo)
gitlab at salsa.debian.org
Sun Oct 29 23:34:37 GMT 2023
Markus Koschany pushed to branch bookworm at Debian Java Maintainers / jetty9
Commits:
2e267962 by Markus Koschany at 2023-10-30T00:34:14+01:00
Import Debian changes 9.4.50-4+deb12u2
jetty9 (9.4.50-4+deb12u2) bookworm-security; urgency=high
.
* Team upload.
* Fix CVE-2023-36478 and CVE-2023-44487:
Two remotely exploitable security vulnerabilities were discovered in Jetty
9, a Java based web server and servlet engine. The HTTP/2 protocol
implementation did not sufficiently verify if HPACK header values exceed
their size limit. Furthermore the HTTP/2 protocol allowed a denial of
service (server resource consumption) because request cancellation can
reset many streams quickly. This problem is also known as Rapid Reset
Attack.
- - - - -
4 changed files:
- debian/changelog
- + debian/patches/CVE-2023-36478.patch
- + debian/patches/CVE-2023-44487.patch
- debian/patches/series
Changes:
=====================================
debian/changelog
=====================================
@@ -1,3 +1,17 @@
+jetty9 (9.4.50-4+deb12u2) bookworm-security; urgency=high
+
+ * Team upload.
+ * Fix CVE-2023-36478 and CVE-2023-44487:
+ Two remotely exploitable security vulnerabilities were discovered in Jetty
+ 9, a Java based web server and servlet engine. The HTTP/2 protocol
+ implementation did not sufficiently verify if HPACK header values exceed
+ their size limit. Furthermore the HTTP/2 protocol allowed a denial of
+ service (server resource consumption) because request cancellation can
+ reset many streams quickly. This problem is also known as Rapid Reset
+ Attack.
+
+ -- Markus Koschany <apo at debian.org> Sun, 29 Oct 2023 16:12:42 +0100
+
jetty9 (9.4.50-4+deb12u1) bookworm-security; urgency=high
* Team upload.
=====================================
debian/patches/CVE-2023-36478.patch
=====================================
The diff for this file was not included because it is too large.
=====================================
debian/patches/CVE-2023-44487.patch
=====================================
@@ -0,0 +1,622 @@
+From: Markus Koschany <apo at debian.org>
+Date: Thu, 26 Oct 2023 20:25:08 +0200
+Subject: CVE-2023-44487
+
+Origin: https://github.com/jetty/jetty.project/commit/2a512c2461282fa790a4c89b8ab5b7df15445b66
+---
+ .../jetty/http2/parser/ContinuationBodyParser.java | 36 +++++++++++----
+ .../jetty/http2/parser/HeaderBlockFragments.java | 33 +++++++++----
+ .../jetty/http2/parser/HeadersBodyParser.java | 37 +++++++++++----
+ .../org/eclipse/jetty/http2/parser/Parser.java | 2 +-
+ .../jetty/http2/parser/PushPromiseBodyParser.java | 13 ++++--
+ .../jetty/http2/parser/ResetBodyParser.java | 8 ++--
+ .../jetty/http2/parser/SettingsBodyParser.java | 29 ++++++++----
+ .../jetty/http2/parser/UnknownBodyParser.java | 1 -
+ .../jetty/http2/frames/ContinuationParseTest.java | 54 ++++++++++++++++++++++
+ .../eclipse/jetty/http2/frames/FrameFloodTest.java | 31 +++++++++++--
+ .../http2/frames/SettingsGenerateParseTest.java | 16 +++----
+ .../AbstractHTTP2ServerConnectionFactory.java | 2 +-
+ 12 files changed, 204 insertions(+), 58 deletions(-)
+
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ContinuationBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ContinuationBodyParser.java
+index 04d26d1..8f32800 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ContinuationBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ContinuationBodyParser.java
+@@ -80,16 +80,28 @@ public class ContinuationBodyParser extends BodyParser
+ int remaining = buffer.remaining();
+ if (remaining < length)
+ {
+- headerBlockFragments.storeFragment(buffer, remaining, false);
++ ContinuationFrame frame = new ContinuationFrame(getStreamId(), false);
++ if (!rateControlOnEvent(frame))
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_continuation_frame_rate");
++
++ if (!headerBlockFragments.storeFragment(buffer, remaining, false))
++ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_continuation_stream");
++
+ length -= remaining;
+ break;
+ }
+ else
+ {
+- boolean last = hasFlag(Flags.END_HEADERS);
+- headerBlockFragments.storeFragment(buffer, length, last);
++ boolean endHeaders = hasFlag(Flags.END_HEADERS);
++ ContinuationFrame frame = new ContinuationFrame(getStreamId(), endHeaders);
++ if (!rateControlOnEvent(frame))
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_continuation_frame_rate");
++
++ if (!headerBlockFragments.storeFragment(buffer, length, endHeaders))
++ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_continuation_stream");
++
+ reset();
+- if (last)
++ if (endHeaders)
+ return onHeaders(buffer);
+ return true;
+ }
+@@ -107,17 +119,21 @@ public class ContinuationBodyParser extends BodyParser
+ {
+ ByteBuffer headerBlock = headerBlockFragments.complete();
+ MetaData metaData = headerBlockParser.parse(headerBlock, headerBlock.remaining());
+- if (metaData == null)
+- return true;
++ HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, headerBlockFragments.getPriorityFrame(), headerBlockFragments.isEndStream());
++ headerBlockFragments.reset();
++
+ if (metaData == HeaderBlockParser.SESSION_FAILURE)
+ return false;
+- HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, headerBlockFragments.getPriorityFrame(), headerBlockFragments.isEndStream());
+- if (metaData == HeaderBlockParser.STREAM_FAILURE)
++
++ if (metaData != HeaderBlockParser.STREAM_FAILURE)
++ {
++ notifyHeaders(frame);
++ }
++ else
+ {
+ if (!rateControlOnEvent(frame))
+- return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_continuation_frame_rate");
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
+ }
+- notifyHeaders(frame);
+ return true;
+ }
+
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockFragments.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockFragments.java
+index be63ba4..3c69d2d 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockFragments.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeaderBlockFragments.java
+@@ -24,22 +24,40 @@ import org.eclipse.jetty.http2.frames.PriorityFrame;
+
+ public class HeaderBlockFragments
+ {
++ private final int maxCapacity;
+ private PriorityFrame priorityFrame;
+- private boolean endStream;
+ private int streamId;
++ private boolean endStream;
+ private ByteBuffer storage;
+
+- public void storeFragment(ByteBuffer fragment, int length, boolean last)
++ public HeaderBlockFragments(int maxCapacity)
++ {
++ this.maxCapacity = maxCapacity;
++ }
++
++ void reset()
++ {
++ priorityFrame = null;
++ streamId = 0;
++ endStream = false;
++ storage = null;
++ }
++
++ public boolean storeFragment(ByteBuffer fragment, int length, boolean last)
+ {
+ if (storage == null)
+ {
+- int space = last ? length : length * 2;
+- storage = ByteBuffer.allocate(space);
++ if (length > maxCapacity)
++ return false;
++ int capacity = last ? length : length * 2;
++ storage = ByteBuffer.allocate(capacity);
+ }
+
+ // Grow the storage if necessary.
+ if (storage.remaining() < length)
+ {
++ if (storage.position() + length > maxCapacity)
++ return false;
+ int space = last ? length : length * 2;
+ int capacity = storage.position() + space;
+ ByteBuffer newStorage = ByteBuffer.allocate(capacity);
+@@ -53,6 +71,7 @@ public class HeaderBlockFragments
+ fragment.limit(fragment.position() + length);
+ storage.put(fragment);
+ fragment.limit(limit);
++ return true;
+ }
+
+ public PriorityFrame getPriorityFrame()
+@@ -77,10 +96,8 @@ public class HeaderBlockFragments
+
+ public ByteBuffer complete()
+ {
+- ByteBuffer result = storage;
+- storage = null;
+- result.flip();
+- return result;
++ storage.flip();
++ return storage;
+ }
+
+ public int getStreamId()
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java
+index b38a286..e222420 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/HeadersBodyParser.java
+@@ -76,8 +76,15 @@ public class HeadersBodyParser extends BodyParser
+ }
+ else
+ {
+- headerBlockFragments.setStreamId(getStreamId());
+- headerBlockFragments.setEndStream(isEndStream());
++ if (headerBlockFragments.getStreamId() != 0)
++ {
++ connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_headers_frame");
++ }
++ else
++ {
++ headerBlockFragments.setStreamId(getStreamId());
++ headerBlockFragments.setEndStream(isEndStream());
++ }
+ }
+ }
+
+@@ -172,6 +179,18 @@ public class HeadersBodyParser extends BodyParser
+ break;
+ }
+ case HEADERS:
++ {
++ if (!hasFlag(Flags.END_HEADERS))
++ {
++ headerBlockFragments.setStreamId(getStreamId());
++ headerBlockFragments.setEndStream(isEndStream());
++ if (hasFlag(Flags.PRIORITY))
++ headerBlockFragments.setPriorityFrame(new PriorityFrame(getStreamId(), parentStreamId, weight, exclusive));
++ }
++ state = State.HEADER_BLOCK;
++ break;
++ }
++ case HEADER_BLOCK:
+ {
+ if (hasFlag(Flags.END_HEADERS))
+ {
+@@ -192,7 +211,7 @@ public class HeadersBodyParser extends BodyParser
+ {
+ HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, null, isEndStream());
+ if (!rateControlOnEvent(frame))
+- connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
+ }
+ }
+ }
+@@ -201,16 +220,14 @@ public class HeadersBodyParser extends BodyParser
+ int remaining = buffer.remaining();
+ if (remaining < length)
+ {
+- headerBlockFragments.storeFragment(buffer, remaining, false);
++ if (!headerBlockFragments.storeFragment(buffer, remaining, false))
++ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_headers_frame");
+ length -= remaining;
+ }
+ else
+ {
+- headerBlockFragments.setStreamId(getStreamId());
+- headerBlockFragments.setEndStream(isEndStream());
+- if (hasFlag(Flags.PRIORITY))
+- headerBlockFragments.setPriorityFrame(new PriorityFrame(getStreamId(), parentStreamId, weight, exclusive));
+- headerBlockFragments.storeFragment(buffer, length, false);
++ if (!headerBlockFragments.storeFragment(buffer, length, false))
++ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_headers_frame");
+ state = State.PADDING;
+ loop = paddingLength == 0;
+ }
+@@ -254,6 +271,6 @@ public class HeadersBodyParser extends BodyParser
+
+ private enum State
+ {
+- PREPARE, PADDING_LENGTH, EXCLUSIVE, PARENT_STREAM_ID, PARENT_STREAM_ID_BYTES, WEIGHT, HEADERS, PADDING
++ PREPARE, PADDING_LENGTH, EXCLUSIVE, PARENT_STREAM_ID, PARENT_STREAM_ID_BYTES, WEIGHT, HEADERS, HEADER_BLOCK, PADDING
+ }
+ }
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java
+index 8044e71..5e2dfd0 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/Parser.java
+@@ -78,7 +78,7 @@ public class Parser
+ Listener listener = wrapper.apply(this.listener);
+ unknownBodyParser = new UnknownBodyParser(headerParser, listener);
+ HeaderBlockParser headerBlockParser = new HeaderBlockParser(headerParser, byteBufferPool, hpackDecoder, unknownBodyParser);
+- HeaderBlockFragments headerBlockFragments = new HeaderBlockFragments();
++ HeaderBlockFragments headerBlockFragments = new HeaderBlockFragments(hpackDecoder.getMaxHeaderListSize());
+ bodyParsers[FrameType.DATA.getType()] = new DataBodyParser(headerParser, listener);
+ bodyParsers[FrameType.HEADERS.getType()] = new HeadersBodyParser(headerParser, listener, headerBlockParser, headerBlockFragments);
+ bodyParsers[FrameType.PRIORITY.getType()] = new PriorityBodyParser(headerParser, listener);
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/PushPromiseBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/PushPromiseBodyParser.java
+index c09405d..f02107d 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/PushPromiseBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/PushPromiseBodyParser.java
+@@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
+ import org.eclipse.jetty.http.MetaData;
+ import org.eclipse.jetty.http2.ErrorCode;
+ import org.eclipse.jetty.http2.Flags;
++import org.eclipse.jetty.http2.frames.HeadersFrame;
+ import org.eclipse.jetty.http2.frames.PushPromiseFrame;
+
+ public class PushPromiseBodyParser extends BodyParser
+@@ -70,13 +71,9 @@ public class PushPromiseBodyParser extends BodyParser
+ length = getBodyLength();
+
+ if (isPadding())
+- {
+ state = State.PADDING_LENGTH;
+- }
+ else
+- {
+ state = State.STREAM_ID;
+- }
+ break;
+ }
+ case PADDING_LENGTH:
+@@ -132,7 +129,15 @@ public class PushPromiseBodyParser extends BodyParser
+ state = State.PADDING;
+ loop = paddingLength == 0;
+ if (metaData != HeaderBlockParser.STREAM_FAILURE)
++ {
+ onPushPromise(streamId, metaData);
++ }
++ else
++ {
++ HeadersFrame frame = new HeadersFrame(getStreamId(), metaData, null, isEndStream());
++ if (!rateControlOnEvent(frame))
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_headers_frame_rate");
++ }
+ }
+ break;
+ }
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ResetBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ResetBodyParser.java
+index bcc80f1..19b072a 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ResetBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/ResetBodyParser.java
+@@ -63,7 +63,7 @@ public class ResetBodyParser extends BodyParser
+ {
+ if (buffer.remaining() >= 4)
+ {
+- return onReset(buffer.getInt());
++ return onReset(buffer, buffer.getInt());
+ }
+ else
+ {
+@@ -78,7 +78,7 @@ public class ResetBodyParser extends BodyParser
+ --cursor;
+ error += currByte << (8 * cursor);
+ if (cursor == 0)
+- return onReset(error);
++ return onReset(buffer, error);
+ break;
+ }
+ default:
+@@ -90,9 +90,11 @@ public class ResetBodyParser extends BodyParser
+ return false;
+ }
+
+- private boolean onReset(int error)
++ private boolean onReset(ByteBuffer buffer, int error)
+ {
+ ResetFrame frame = new ResetFrame(getStreamId(), error);
++ if (!rateControlOnEvent(frame))
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_rst_stream_frame_rate");
+ reset();
+ notifyReset(frame);
+ return true;
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java
+index 5ee0252..fe9eaf0 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/SettingsBodyParser.java
+@@ -73,12 +73,22 @@ public class SettingsBodyParser extends BodyParser
+ @Override
+ protected void emptyBody(ByteBuffer buffer)
+ {
++ if (!validateFrame(buffer, getStreamId(), 0))
++ return;
+ boolean isReply = hasFlag(Flags.ACK);
+ SettingsFrame frame = new SettingsFrame(Collections.emptyMap(), isReply);
+- if (!isReply && !rateControlOnEvent(frame))
+- connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_settings_frame_rate");
+- else
+- onSettings(frame);
++ onSettings(buffer, frame);
++ }
++
++ private boolean validateFrame(ByteBuffer buffer, int streamId, int bodyLength)
++ {
++ // SPEC: wrong streamId is treated as connection error.
++ if (streamId != 0)
++ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_settings_frame");
++ // SPEC: reply with body is treated as connection error.
++ if (hasFlag(Flags.ACK) && bodyLength > 0)
++ return connectionFailure(buffer, ErrorCode.FRAME_SIZE_ERROR.code, "invalid_settings_frame");
++ return true;
+ }
+
+ @Override
+@@ -95,9 +105,8 @@ public class SettingsBodyParser extends BodyParser
+ {
+ case PREPARE:
+ {
+- // SPEC: wrong streamId is treated as connection error.
+- if (streamId != 0)
+- return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_settings_frame");
++ if (!validateFrame(buffer, streamId, bodyLength))
++ return false;
+ length = bodyLength;
+ settings = new HashMap<>();
+ state = State.SETTING_ID;
+@@ -211,11 +220,13 @@ public class SettingsBodyParser extends BodyParser
+ return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_settings_max_frame_size");
+
+ SettingsFrame frame = new SettingsFrame(settings, hasFlag(Flags.ACK));
+- return onSettings(frame);
++ return onSettings(buffer, frame);
+ }
+
+- private boolean onSettings(SettingsFrame frame)
++ private boolean onSettings(ByteBuffer buffer, SettingsFrame frame)
+ {
++ if (!rateControlOnEvent(frame))
++ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_settings_frame_rate");
+ reset();
+ notifySettings(frame);
+ return true;
+diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/UnknownBodyParser.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/UnknownBodyParser.java
+index 86a8628..23ca493 100644
+--- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/UnknownBodyParser.java
++++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/parser/UnknownBodyParser.java
+@@ -40,7 +40,6 @@ public class UnknownBodyParser extends BodyParser
+ boolean parsed = cursor == 0;
+ if (parsed && !rateControlOnEvent(new UnknownFrame(getFrameType())))
+ return connectionFailure(buffer, ErrorCode.ENHANCE_YOUR_CALM_ERROR.code, "invalid_unknown_frame_rate");
+-
+ return parsed;
+ }
+
+diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java
+index 9fb1bbf..54a7cde 100644
+--- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java
++++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java
+@@ -22,6 +22,8 @@ import java.nio.ByteBuffer;
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.function.UnaryOperator;
++import java.util.concurrent.atomic.AtomicBoolean;
++import java.util.stream.IntStream;
+
+ import org.eclipse.jetty.http.HostPortHttpField;
+ import org.eclipse.jetty.http.HttpField;
+@@ -38,6 +40,8 @@ import org.eclipse.jetty.io.ByteBufferPool;
+ import org.eclipse.jetty.io.MappedByteBufferPool;
+ import org.junit.jupiter.api.Test;
+
++import static org.hamcrest.MatcherAssert.assertThat;
++import static org.hamcrest.Matchers.greaterThan;
+ import static org.junit.jupiter.api.Assertions.assertEquals;
+ import static org.junit.jupiter.api.Assertions.assertNull;
+ import static org.junit.jupiter.api.Assertions.assertTrue;
+@@ -160,4 +164,54 @@ public class ContinuationParseTest
+ assertNull(priority);
+ }
+ }
++
++ @Test
++ public void testLargeHeadersBlock() throws Exception
++ {
++ // Use a ByteBufferPool with a small factor, so that the accumulation buffer is not too large.
++ ByteBufferPool byteBufferPool = new MappedByteBufferPool(128);
++ // A small max headers size, used for both accumulation and decoding.
++ int maxHeadersSize = 512;
++ Parser parser = new Parser(byteBufferPool, maxHeadersSize);
++ // Specify headers block size to generate CONTINUATION frames.
++ int maxHeadersBlockFragment = 128;
++ HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder(), maxHeadersBlockFragment);
++
++ int streamId = 13;
++ HttpFields fields = new HttpFields();
++ fields.put("Accept", "text/html");
++ // Large header that generates a large headers block.
++ StringBuilder large = new StringBuilder();
++ IntStream.range(0, 256).forEach(i -> large.append("Jetty"));
++ fields.put("User-Agent", large.toString());
++
++ MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1);
++
++ ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
++ generator.generateHeaders(lease, streamId, metaData, null, true);
++ List<ByteBuffer> byteBuffers = lease.getByteBuffers();
++ assertThat(byteBuffers.stream().mapToInt(ByteBuffer::remaining).sum(), greaterThan(maxHeadersSize));
++
++ AtomicBoolean failed = new AtomicBoolean();
++ parser.init(new Parser.Listener.Adapter()
++ {
++ @Override
++ public void onConnectionFailure(int error, String reason)
++ {
++ failed.set(true);
++ }
++ });
++ // Set a large max headers size for decoding, to ensure
++ // the failure is due to accumulation, not decoding.
++ parser.getHpackDecoder().setMaxHeaderListSize(10 * maxHeadersSize);
++
++ for (ByteBuffer byteBuffer : byteBuffers)
++ {
++ parser.parse(byteBuffer);
++ if (failed.get())
++ break;
++ }
++
++ assertTrue(failed.get());
++ }
+ }
+diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/FrameFloodTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/FrameFloodTest.java
+index f9ee47f..2a1b187 100644
+--- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/FrameFloodTest.java
++++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/FrameFloodTest.java
+@@ -95,21 +95,29 @@ public class FrameFloodTest
+ }
+
+ @Test
+- public void testSettingsFrameFlood()
++ public void testEmptySettingsFrameFlood()
+ {
+ byte[] payload = new byte[0];
+ testFrameFlood(null, frameFrom(payload.length, FrameType.SETTINGS.getType(), 0, 0, payload));
+ }
+
++ @Test
++ public void testSettingsFrameFlood()
++ {
++ // | Key0 | Key1 | Value0 | Value1 | Value2 | Value3 |
++ byte[] payload = new byte[]{0, 8, 0, 0, 0, 1};
++ testFrameFlood(null, frameFrom(payload.length, FrameType.SETTINGS.getType(), 0, 0, payload));
++ }
++
+ @Test
+ public void testPingFrameFlood()
+ {
+ byte[] payload = {0, 0, 0, 0, 0, 0, 0, 0};
+ testFrameFlood(null, frameFrom(payload.length, FrameType.PING.getType(), 0, 0, payload));
+ }
+-
++
+ @Test
+- public void testContinuationFrameFlood()
++ public void testEmptyContinuationFrameFlood()
+ {
+ int streamId = 13;
+ byte[] headersPayload = new byte[0];
+@@ -118,6 +126,23 @@ public class FrameFloodTest
+ testFrameFlood(headersBytes, frameFrom(continuationPayload.length, FrameType.CONTINUATION.getType(), 0, streamId, continuationPayload));
+ }
+
++ @Test
++ public void testContinuationFrameFlood()
++ {
++ int streamId = 13;
++ byte[] headersPayload = new byte[0];
++ byte[] headersBytes = frameFrom(headersPayload.length, FrameType.HEADERS.getType(), 0, streamId, headersPayload);
++ byte[] continuationPayload = new byte[1];
++ testFrameFlood(headersBytes, frameFrom(continuationPayload.length, FrameType.CONTINUATION.getType(), 0, streamId, continuationPayload));
++ }
++
++ @Test
++ public void testResetStreamFrameFlood()
++ {
++ byte[] payload = {0, 0, 0, 0};
++ testFrameFlood(null, frameFrom(payload.length, FrameType.RST_STREAM.getType(), 0, 13, payload));
++ }
++
+ @Test
+ public void testUnknownFrameFlood()
+ {
+diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/SettingsGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/SettingsGenerateParseTest.java
+index 83ab018..4cc6a45 100644
+--- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/SettingsGenerateParseTest.java
++++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/SettingsGenerateParseTest.java
+@@ -36,6 +36,7 @@ import org.eclipse.jetty.io.MappedByteBufferPool;
+ import org.junit.jupiter.api.Test;
+
+ import static org.junit.jupiter.api.Assertions.assertEquals;
++import static org.junit.jupiter.api.Assertions.assertFalse;
+ import static org.junit.jupiter.api.Assertions.assertTrue;
+
+ public class SettingsGenerateParseTest
+@@ -45,8 +46,7 @@ public class SettingsGenerateParseTest
+ @Test
+ public void testGenerateParseNoSettings()
+ {
+-
+- List<SettingsFrame> frames = testGenerateParse(Collections.<Integer, Integer>emptyMap());
++ List<SettingsFrame> frames = testGenerateParse(Collections.<Integer, Integer>emptyMap(), true);
+ assertEquals(1, frames.size());
+ SettingsFrame frame = frames.get(0);
+ assertEquals(0, frame.getSettings().size());
+@@ -63,7 +63,7 @@ public class SettingsGenerateParseTest
+ int key2 = 19;
+ Integer value2 = 23;
+ settings1.put(key2, value2);
+- List<SettingsFrame> frames = testGenerateParse(settings1);
++ List<SettingsFrame> frames = testGenerateParse(settings1, false);
+ assertEquals(1, frames.size());
+ SettingsFrame frame = frames.get(0);
+ Map<Integer, Integer> settings2 = frame.getSettings();
+@@ -72,7 +72,7 @@ public class SettingsGenerateParseTest
+ assertEquals(value2, settings2.get(key2));
+ }
+
+- private List<SettingsFrame> testGenerateParse(Map<Integer, Integer> settings)
++ private List<SettingsFrame> testGenerateParse(Map<Integer, Integer> settings, boolean reply)
+ {
+ SettingsGenerator generator = new SettingsGenerator(new HeaderGenerator());
+
+@@ -91,7 +91,7 @@ public class SettingsGenerateParseTest
+ for (int i = 0; i < 2; ++i)
+ {
+ ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
+- generator.generateSettings(lease, settings, true);
++ generator.generateSettings(lease, settings, reply);
+
+ frames.clear();
+ for (ByteBuffer buffer : lease.getByteBuffers())
+@@ -125,7 +125,7 @@ public class SettingsGenerateParseTest
+ Map<Integer, Integer> settings1 = new HashMap<>();
+ settings1.put(13, 17);
+ ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
+- generator.generateSettings(lease, settings1, true);
++ generator.generateSettings(lease, settings1, false);
+ // Modify the length of the frame to make it invalid
+ ByteBuffer bytes = lease.getByteBuffers().get(0);
+ bytes.putShort(1, (short)(bytes.getShort(1) - 1));
+@@ -166,7 +166,7 @@ public class SettingsGenerateParseTest
+ for (int i = 0; i < 2; ++i)
+ {
+ ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool);
+- generator.generateSettings(lease, settings1, true);
++ generator.generateSettings(lease, settings1, false);
+
+ frames.clear();
+ for (ByteBuffer buffer : lease.getByteBuffers())
+@@ -182,7 +182,7 @@ public class SettingsGenerateParseTest
+ Map<Integer, Integer> settings2 = frame.getSettings();
+ assertEquals(1, settings2.size());
+ assertEquals(value, settings2.get(key));
+- assertTrue(frame.isReply());
++ assertFalse(frame.isReply());
+ }
+ }
+
+diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
+index 9d6306e..554ecfd 100644
+--- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
++++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java
+@@ -60,7 +60,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
+ private int maxHeaderBlockFragment = 0;
+ private int maxFrameLength = Frame.DEFAULT_MAX_LENGTH;
+ private int maxSettingsKeys = SettingsFrame.DEFAULT_MAX_KEYS;
+- private RateControl.Factory rateControlFactory = new WindowRateControl.Factory(50);
++ private RateControl.Factory rateControlFactory = new WindowRateControl.Factory(128);
+ private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
+ private long streamIdleTimeout;
+
=====================================
debian/patches/series
=====================================
@@ -11,3 +11,5 @@ CVE-2023-26049.patch
CVE-2023-40167.patch
CVE-2023-41900.patch
CVE-2023-36479.patch
+CVE-2023-44487.patch
+CVE-2023-36478.patch
View it on GitLab: https://salsa.debian.org/java-team/jetty9/-/commit/2e267962b83db143c831e713f44927a680f1e1fb
--
View it on GitLab: https://salsa.debian.org/java-team/jetty9/-/commit/2e267962b83db143c831e713f44927a680f1e1fb
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20231029/7ec7dc5b/attachment.htm>
More information about the pkg-java-commits
mailing list