Version in base suite: 10.1.6-1+deb12u1 Base version: tomcat10_10.1.6-1+deb12u1 Target version: tomcat10_10.1.6-1+deb12u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/tomcat10/tomcat10_10.1.6-1+deb12u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/t/tomcat10/tomcat10_10.1.6-1+deb12u2.dsc changelog | 21 ++ patches/CVE-2023-46589.patch | 317 +++++++++++++++++++++++++++++++++++++++++++ patches/CVE-2024-23672.patch | 220 +++++++++++++++++++++++++++++ patches/CVE-2024-24549.patch | 46 ++++++ patches/series | 3 5 files changed, 607 insertions(+) diff -Nru tomcat10-10.1.6/debian/changelog tomcat10-10.1.6/debian/changelog --- tomcat10-10.1.6/debian/changelog 2023-10-10 16:33:08.000000000 +0000 +++ tomcat10-10.1.6/debian/changelog 2024-04-15 20:05:02.000000000 +0000 @@ -1,3 +1,24 @@ +tomcat10 (10.1.6-1+deb12u2) bookworm-security; urgency=high + + * Team upload. + * Fix CVE-2023-46589: + Improper Input Validation vulnerability in Apache Tomcat. Tomcat 10 did not + correctly parse HTTP trailer headers. A trailer header that exceeded the + header size limit could cause Tomcat to treat a single request as multiple + requests leading to the possibility of request smuggling when behind a + reverse proxy. + * Fix CVE-2024-24549: + Denial of Service due to improper input validation vulnerability for + HTTP/2. When processing an HTTP/2 request, if the request exceeded any of + the configured limits for headers, the associated HTTP/2 stream was not + reset until after all of the headers had been processed. + * Fix CVE-2024-23672: + Denial of Service via incomplete cleanup vulnerability. It was possible for + WebSocket clients to keep WebSocket connections open leading to increased + resource consumption. + + -- Markus Koschany Mon, 15 Apr 2024 22:05:02 +0200 + tomcat10 (10.1.6-1+deb12u1) bookworm-security; urgency=high * Fix CVE-2023-45648: Request smuggling. Tomcat did not correctly parse HTTP diff -Nru tomcat10-10.1.6/debian/patches/CVE-2023-46589.patch tomcat10-10.1.6/debian/patches/CVE-2023-46589.patch --- tomcat10-10.1.6/debian/patches/CVE-2023-46589.patch 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.6/debian/patches/CVE-2023-46589.patch 2024-04-15 19:52:33.000000000 +0000 @@ -0,0 +1,317 @@ +From: Markus Koschany +Date: Wed, 10 Apr 2024 17:02:36 +0200 +Subject: CVE-2023-46589 + +Bug-Debian: https://bugs.debian.org/1057082 +Origin: https://github.com/apache/tomcat/commit/b5776d769bffeade865061bc8ecbeb2b56167b08 +--- + .../catalina/connector/BadRequestException.java | 68 +++++++++++++++++++ + .../catalina/connector/ClientAbortException.java | 4 +- + .../org/apache/catalina/connector/InputBuffer.java | 19 +++++- + .../catalina/core/ApplicationDispatcher.java | 6 +- + .../apache/catalina/core/StandardWrapperValve.java | 6 +- + .../http11/filters/TestChunkedInputFilter.java | 77 ++++++++++++++++++++++ + webapps/docs/changelog.xml | 5 ++ + 7 files changed, 174 insertions(+), 11 deletions(-) + create mode 100644 java/org/apache/catalina/connector/BadRequestException.java + +diff --git a/java/org/apache/catalina/connector/BadRequestException.java b/java/org/apache/catalina/connector/BadRequestException.java +new file mode 100644 +index 0000000..71a792d +--- /dev/null ++++ b/java/org/apache/catalina/connector/BadRequestException.java +@@ -0,0 +1,68 @@ ++/* ++ * Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF 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.apache.catalina.connector; ++ ++import java.io.IOException; ++ ++/** ++ * Extend IOException to identify it as being caused by a bad request from a remote client. ++ */ ++public class BadRequestException extends IOException { ++ ++ private static final long serialVersionUID = 1L; ++ ++ ++ // ------------------------------------------------------------ Constructors ++ ++ /** ++ * Construct a new BadRequestException with no other information. ++ */ ++ public BadRequestException() { ++ super(); ++ } ++ ++ ++ /** ++ * Construct a new BadRequestException for the specified message. ++ * ++ * @param message Message describing this exception ++ */ ++ public BadRequestException(String message) { ++ super(message); ++ } ++ ++ ++ /** ++ * Construct a new BadRequestException for the specified throwable. ++ * ++ * @param throwable Throwable that caused this exception ++ */ ++ public BadRequestException(Throwable throwable) { ++ super(throwable); ++ } ++ ++ ++ /** ++ * Construct a new BadRequestException for the specified message and throwable. ++ * ++ * @param message Message describing this exception ++ * @param throwable Throwable that caused this exception ++ */ ++ public BadRequestException(String message, Throwable throwable) { ++ super(message, throwable); ++ } ++} +diff --git a/java/org/apache/catalina/connector/ClientAbortException.java b/java/org/apache/catalina/connector/ClientAbortException.java +index fa469f9..a3ba607 100644 +--- a/java/org/apache/catalina/connector/ClientAbortException.java ++++ b/java/org/apache/catalina/connector/ClientAbortException.java +@@ -16,15 +16,13 @@ + */ + package org.apache.catalina.connector; + +-import java.io.IOException; +- + /** + * Extend IOException to identify it as being caused by an abort of a request by + * a remote client. + * + * @author Glenn L. Nielsen + */ +-public final class ClientAbortException extends IOException { ++public final class ClientAbortException extends BadRequestException { + + private static final long serialVersionUID = 1L; + +diff --git a/java/org/apache/catalina/connector/InputBuffer.java b/java/org/apache/catalina/connector/InputBuffer.java +index da736cc..7ed372f 100644 +--- a/java/org/apache/catalina/connector/InputBuffer.java ++++ b/java/org/apache/catalina/connector/InputBuffer.java +@@ -29,6 +29,7 @@ import java.util.Map; + import java.util.concurrent.ConcurrentHashMap; + + import jakarta.servlet.ReadListener; ++import jakarta.servlet.RequestDispatcher; + + import org.apache.catalina.security.SecurityUtil; + import org.apache.coyote.ActionCode; +@@ -314,10 +315,24 @@ public class InputBuffer extends Reader + + try { + return coyoteRequest.doRead(this); ++ } catch (BadRequestException bre) { ++ // Set flag used by asynchronous processing to detect errors on non-container threads ++ coyoteRequest.setErrorException(bre); ++ // In synchronous processing, this exception may be swallowed by the application so set error flags here. ++ coyoteRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, bre); ++ coyoteRequest.getResponse().setStatus(400); ++ coyoteRequest.getResponse().setError(); ++ // Make the exception visible to the application ++ throw bre; + } catch (IOException ioe) { ++ // Set flag used by asynchronous processing to detect errors on non-container threads + coyoteRequest.setErrorException(ioe); +- // An IOException on a read is almost always due to +- // the remote client aborting the request. ++ // In synchronous processing, this exception may be swallowed by the application so set error flags here. ++ coyoteRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe); ++ coyoteRequest.getResponse().setStatus(400); ++ coyoteRequest.getResponse().setError(); ++ // Any other IOException on a read is almost always due to the remote client aborting the request. ++ // Make the exception visible to the application + throw new ClientAbortException(ioe); + } + } +diff --git a/java/org/apache/catalina/core/ApplicationDispatcher.java b/java/org/apache/catalina/core/ApplicationDispatcher.java +index f9b82d5..9e0fd51 100644 +--- a/java/org/apache/catalina/core/ApplicationDispatcher.java ++++ b/java/org/apache/catalina/core/ApplicationDispatcher.java +@@ -41,7 +41,7 @@ import org.apache.catalina.AsyncDispatcher; + import org.apache.catalina.Context; + import org.apache.catalina.Globals; + import org.apache.catalina.Wrapper; +-import org.apache.catalina.connector.ClientAbortException; ++import org.apache.catalina.connector.BadRequestException; + import org.apache.catalina.connector.Request; + import org.apache.catalina.connector.RequestFacade; + import org.apache.catalina.connector.Response; +@@ -642,7 +642,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher + filterChain.doFilter(request, response); + } + // Servlet Service Method is called by the FilterChain +- } catch (ClientAbortException e) { ++ } catch (BadRequestException e) { + ioException = e; + } catch (IOException e) { + wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e); +@@ -653,7 +653,7 @@ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher + wrapper.unavailable(e); + } catch (ServletException e) { + Throwable rootCause = StandardWrapper.getRootCause(e); +- if (!(rootCause instanceof ClientAbortException)) { ++ if (!(rootCause instanceof BadRequestException)) { + wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), + rootCause); + } +diff --git a/java/org/apache/catalina/core/StandardWrapperValve.java b/java/org/apache/catalina/core/StandardWrapperValve.java +index bbbda3c..02054aa 100644 +--- a/java/org/apache/catalina/core/StandardWrapperValve.java ++++ b/java/org/apache/catalina/core/StandardWrapperValve.java +@@ -31,7 +31,7 @@ import org.apache.catalina.Container; + import org.apache.catalina.Context; + import org.apache.catalina.Globals; + import org.apache.catalina.LifecycleException; +-import org.apache.catalina.connector.ClientAbortException; ++import org.apache.catalina.connector.BadRequestException; + import org.apache.catalina.connector.Request; + import org.apache.catalina.connector.Response; + import org.apache.catalina.valves.ValveBase; +@@ -168,7 +168,7 @@ final class StandardWrapperValve extends ValveBase { + } + + } +- } catch (ClientAbortException | CloseNowException e) { ++ } catch (BadRequestException | CloseNowException e) { + if (container.getLogger().isDebugEnabled()) { + container.getLogger().debug( + sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e); +@@ -189,7 +189,7 @@ final class StandardWrapperValve extends ValveBase { + // do not want to do exception(request, response, e) processing + } catch (ServletException e) { + Throwable rootCause = StandardWrapper.getRootCause(e); +- if (!(rootCause instanceof ClientAbortException)) { ++ if (!(rootCause instanceof BadRequestException)) { + container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), + context.getName(), e.getMessage()), rootCause); + } +diff --git a/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java b/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java +index 2230fe9..3454d8d 100644 +--- a/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java ++++ b/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java +@@ -428,6 +428,83 @@ public class TestChunkedInputFilter extends TomcatBaseTest { + } + } + ++ ++ @Test ++ public void testTrailerHeaderNameNotTokenThrowException() throws Exception { ++ doTestTrailerHeaderNameNotToken(false); ++ } ++ ++ @Test ++ public void testTrailerHeaderNameNotTokenSwallowException() throws Exception { ++ doTestTrailerHeaderNameNotToken(true); ++ } ++ ++ private void doTestTrailerHeaderNameNotToken(boolean swallowException) throws Exception { ++ ++ // Setup Tomcat instance ++ Tomcat tomcat = getTomcatInstance(); ++ ++ // No file system docBase required ++ Context ctx = tomcat.addContext("", null); ++ ++ Tomcat.addServlet(ctx, "servlet", new SwallowBodyServlet(swallowException)); ++ ctx.addServletMappingDecoded("/", "servlet"); ++ ++ tomcat.start(); ++ ++ String[] request = new String[]{ ++ "POST / HTTP/1.1" + SimpleHttpClient.CRLF + ++ "Host: localhost" + SimpleHttpClient.CRLF + ++ "Transfer-encoding: chunked" + SimpleHttpClient.CRLF + ++ "Content-Type: application/x-www-form-urlencoded" + SimpleHttpClient.CRLF + ++ "Connection: close" + SimpleHttpClient.CRLF + ++ SimpleHttpClient.CRLF + ++ "3" + SimpleHttpClient.CRLF + ++ "a=0" + SimpleHttpClient.CRLF + ++ "4" + SimpleHttpClient.CRLF + ++ "&b=1" + SimpleHttpClient.CRLF + ++ "0" + SimpleHttpClient.CRLF + ++ "x@trailer: Test" + SimpleHttpClient.CRLF + ++ SimpleHttpClient.CRLF }; ++ ++ TrailerClient client = new TrailerClient(tomcat.getConnector().getLocalPort()); ++ client.setRequest(request); ++ ++ client.connect(); ++ client.processRequest(); ++ // Expected to fail because of invalid trailer header name ++ Assert.assertTrue(client.getResponseLine(), client.isResponse400()); ++ } ++ ++ private static class SwallowBodyServlet extends HttpServlet { ++ private static final long serialVersionUID = 1L; ++ ++ private final boolean swallowException; ++ ++ SwallowBodyServlet(boolean swallowException) { ++ this.swallowException = swallowException; ++ } ++ ++ @Override ++ protected void doPost(HttpServletRequest req, HttpServletResponse resp) ++ throws ServletException, IOException { ++ resp.setContentType("text/plain"); ++ PrintWriter pw = resp.getWriter(); ++ ++ // Read the body ++ InputStream is = req.getInputStream(); ++ try { ++ while (is.read() > -1) { ++ } ++ pw.write("OK"); ++ } catch (IOException ioe) { ++ if (!swallowException) { ++ throw ioe; ++ } ++ } ++ } ++ } ++ + private static class EchoHeaderServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + +diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml +index 329d923..0fb33f4 100644 +--- a/webapps/docs/changelog.xml ++++ b/webapps/docs/changelog.xml +@@ -145,6 +145,11 @@ + RemoteIpFilter determines that this request was submitted + via a secure channel. (lihan) + ++ ++ Ensure that an IOException during the reading of the ++ request triggers always error handling, regardless of whether the ++ application swallows the exception. (markt) ++ + + + diff -Nru tomcat10-10.1.6/debian/patches/CVE-2024-23672.patch tomcat10-10.1.6/debian/patches/CVE-2024-23672.patch --- tomcat10-10.1.6/debian/patches/CVE-2024-23672.patch 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.6/debian/patches/CVE-2024-23672.patch 2024-04-15 19:49:38.000000000 +0000 @@ -0,0 +1,220 @@ +From: Markus Koschany +Date: Wed, 10 Apr 2024 21:54:01 +0200 +Subject: CVE-2024-23672 + +Bug-Debian: https://bugs.debian.org/1066877 +Origin: https://github.com/apache/tomcat/commit/0052b374684b613b0c849899b325ebe334ac6501 +--- + java/org/apache/tomcat/websocket/Constants.java | 6 ++ + java/org/apache/tomcat/websocket/WsSession.java | 66 ++++++++++++++++++++-- + .../tomcat/websocket/WsWebSocketContainer.java | 9 ++- + .../tomcat/websocket/server/WsServerContainer.java | 3 +- + webapps/docs/web-socket-howto.xml | 7 +++ + 5 files changed, 82 insertions(+), 9 deletions(-) + +diff --git a/java/org/apache/tomcat/websocket/Constants.java b/java/org/apache/tomcat/websocket/Constants.java +index c83ab4c..325014b 100644 +--- a/java/org/apache/tomcat/websocket/Constants.java ++++ b/java/org/apache/tomcat/websocket/Constants.java +@@ -19,6 +19,7 @@ package org.apache.tomcat.websocket; + import java.util.ArrayList; + import java.util.Collections; + import java.util.List; ++import java.util.concurrent.TimeUnit; + + import jakarta.websocket.ClientEndpointConfig; + import jakarta.websocket.Extension; +@@ -130,6 +131,11 @@ public class Constants { + // Milliseconds so this is 20 seconds + public static final long DEFAULT_BLOCKING_SEND_TIMEOUT = 20 * 1000; + ++ // Configuration for session close timeout ++ public static final String SESSION_CLOSE_TIMEOUT_PROPERTY = "org.apache.tomcat.websocket.SESSION_CLOSE_TIMEOUT"; ++ // Default is 30 seconds - setting is in milliseconds ++ public static final long DEFAULT_SESSION_CLOSE_TIMEOUT = TimeUnit.SECONDS.toMillis(30); ++ + // Configuration for read idle timeout on WebSocket session + public static final String READ_IDLE_TIMEOUT_MS = "org.apache.tomcat.websocket.READ_IDLE_TIMEOUT_MS"; + +diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java +index c7e3319..2c38a41 100644 +--- a/java/org/apache/tomcat/websocket/WsSession.java ++++ b/java/org/apache/tomcat/websocket/WsSession.java +@@ -27,6 +27,7 @@ import java.util.List; + import java.util.Map; + import java.util.Set; + import java.util.concurrent.ConcurrentHashMap; ++import java.util.concurrent.TimeUnit; + import java.util.concurrent.atomic.AtomicLong; + + import javax.naming.NamingException; +@@ -115,6 +116,7 @@ public class WsSession implements Session { + private volatile long lastActiveRead = System.currentTimeMillis(); + private volatile long lastActiveWrite = System.currentTimeMillis(); + private Map futures = new ConcurrentHashMap<>(); ++ private volatile Long sessionCloseTimeoutExpiry; + + + /** +@@ -616,10 +618,17 @@ public class WsSession implements Session { + state = State.OUTPUT_CLOSED; + + sendCloseMessage(closeReasonMessage); ++ fireEndpointOnClose(closeReasonLocal); + if (closeSocket) { +- wsRemoteEndpoint.close(); ++ closeConnection(); ++ } else { ++ /* ++ * Set close timeout. If the client fails to send a close message response within the timeout, the session ++ * and the connection will be closed when the timeout expires. ++ */ ++ sessionCloseTimeoutExpiry = ++ Long.valueOf(System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(getSessionCloseTimeout())); + } +- fireEndpointOnClose(closeReasonLocal); + } + } + +@@ -657,7 +666,49 @@ public class WsSession implements Session { + state = State.CLOSED; + + // Close the socket +- wsRemoteEndpoint.close(); ++ closeConnection(); ++ } ++ } ++ } ++ ++ private void closeConnection() { ++ /* ++ * Close the network connection. ++ */ ++ wsRemoteEndpoint.close(); ++ /* ++ * Don't unregister the session until the connection is fully closed since webSocketContainer is responsible for ++ * tracking the session close timeout. ++ */ ++ webSocketContainer.unregisterSession(getSessionMapKey(), this); ++ } ++ ++ ++ /* ++ * Returns the session close timeout in milliseconds ++ */ ++ protected long getSessionCloseTimeout() { ++ long result = 0; ++ Object obj = userProperties.get(Constants.SESSION_CLOSE_TIMEOUT_PROPERTY); ++ if (obj instanceof Long) { ++ result = ((Long) obj).intValue(); ++ } ++ if (result <= 0) { ++ result = Constants.DEFAULT_SESSION_CLOSE_TIMEOUT; ++ } ++ return result; ++ } ++ ++ ++ protected void checkCloseTimeout() { ++ // Skip the check if no session close timeout has been set. ++ if (sessionCloseTimeoutExpiry != null) { ++ // Check if the timeout has expired. ++ if (System.nanoTime() - sessionCloseTimeoutExpiry.longValue() > 0) { ++ // Check if the session has been closed in another thread while the timeout was being processed. ++ if (state == State.CLOSED) { ++ closeConnection(); ++ } + } + } + } +@@ -735,7 +786,7 @@ public class WsSession implements Session { + if (log.isDebugEnabled()) { + log.debug(sm.getString("wsSession.sendCloseFail", id), e); + } +- wsRemoteEndpoint.close(); ++ closeConnection(); + // Failure to send a close message is not unexpected in the case of + // an abnormal closure (usually triggered by a failure to read/write + // from/to the client. In this case do not trigger the endpoint's +@@ -743,8 +794,6 @@ public class WsSession implements Session { + if (closeCode != CloseCodes.CLOSED_ABNORMALLY) { + localEndpoint.onError(this, e); + } +- } finally { +- webSocketContainer.unregisterSession(getSessionMapKey(), this); + } + } + +@@ -875,6 +924,11 @@ public class WsSession implements Session { + @Override + public Principal getUserPrincipal() { + checkState(); ++ return getUserPrincipalInternal(); ++ } ++ ++ ++ public Principal getUserPrincipalInternal() { + return userPrincipal; + } + +diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java +index bed9590..f00cfb7 100644 +--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java ++++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java +@@ -641,7 +641,12 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce + synchronized (endPointSessionMapLock) { + Set sessions = endpointSessionMap.get(key); + if (sessions != null) { +- result.addAll(sessions); ++ // Some sessions may be in the process of closing ++ for (WsSession session : sessions) { ++ if (session.isOpen()) { ++ result.add(session); ++ } ++ } + } + } + return result; +@@ -1110,8 +1115,10 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce + if (backgroundProcessCount >= processPeriod) { + backgroundProcessCount = 0; + ++ // Check all registered sessions. + for (WsSession wsSession : sessions.keySet()) { + wsSession.checkExpiration(); ++ wsSession.checkCloseTimeout(); + } + } + +diff --git a/java/org/apache/tomcat/websocket/server/WsServerContainer.java b/java/org/apache/tomcat/websocket/server/WsServerContainer.java +index 27533e9..0b38b47 100644 +--- a/java/org/apache/tomcat/websocket/server/WsServerContainer.java ++++ b/java/org/apache/tomcat/websocket/server/WsServerContainer.java +@@ -383,8 +383,7 @@ public class WsServerContainer extends WsWebSocketContainer + */ + @Override + protected void unregisterSession(Object key, WsSession wsSession) { +- if (wsSession.getUserPrincipal() != null && +- wsSession.getHttpSessionId() != null) { ++ if (wsSession.getUserPrincipalInternal() != null && wsSession.getHttpSessionId() != null) { + unregisterAuthenticatedSession(wsSession, + wsSession.getHttpSessionId()); + } +diff --git a/webapps/docs/web-socket-howto.xml b/webapps/docs/web-socket-howto.xml +index 20cf2ca..2aaa808 100644 +--- a/webapps/docs/web-socket-howto.xml ++++ b/webapps/docs/web-socket-howto.xml +@@ -64,6 +64,13 @@ + the timeout to use in milliseconds. For an infinite timeout, use + -1.

+ ++

The session close timeout defaults to 30000 milliseconds (30 seconds). This ++ may be changed by setting the property ++ org.apache.tomcat.websocket.SESSION_CLOSE_TIMEOUT in the user ++ properties collection attached to the WebSocket session. The value assigned ++ to this property should be a Long and represents the timeout to ++ use in milliseconds. Values less than or equal to zero will be ignored.

++ +

In addition to the Session.setMaxIdleTimeout(long) method which + is part of the Jakarta WebSocket API, Tomcat provides greater control of the + timing out the session due to lack of activity. Setting the property diff -Nru tomcat10-10.1.6/debian/patches/CVE-2024-24549.patch tomcat10-10.1.6/debian/patches/CVE-2024-24549.patch --- tomcat10-10.1.6/debian/patches/CVE-2024-24549.patch 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.6/debian/patches/CVE-2024-24549.patch 2024-04-15 19:51:15.000000000 +0000 @@ -0,0 +1,46 @@ +From: Markus Koschany +Date: Fri, 5 Apr 2024 15:54:58 +0200 +Subject: CVE-2024-24549 + +Bug-Debian: https://bugs.debian.org/1066878 +Origin: https://github.com/apache/tomcat/commit/d07c82194edb69d99b438828fe2cbfadbb207843 +--- + java/org/apache/coyote/http2/Http2Parser.java | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java +index c9cee2e..207eefb 100644 +--- a/java/org/apache/coyote/http2/Http2Parser.java ++++ b/java/org/apache/coyote/http2/Http2Parser.java +@@ -280,6 +280,9 @@ class Http2Parser { + + swallowPayload(streamId, FrameType.HEADERS.getId(), padLength, true, buffer); + ++ // Validate the headers so far ++ hpackDecoder.getHeaderEmitter().validateHeaders(); ++ + if (Flags.isEndOfHeaders(flags)) { + onHeadersComplete(streamId); + } else { +@@ -452,6 +455,9 @@ class Http2Parser { + + readHeaderPayload(streamId, payloadSize, buffer); + ++ // Validate the headers so far ++ hpackDecoder.getHeaderEmitter().validateHeaders(); ++ + if (endOfHeaders) { + headersCurrentStream = -1; + onHeadersComplete(streamId); +@@ -613,11 +619,6 @@ class Http2Parser { + Http2Error.COMPRESSION_ERROR); + } + +- // Delay validation (and triggering any exception) until this point +- // since all the headers still have to be read if a StreamException is +- // going to be thrown. +- hpackDecoder.getHeaderEmitter().validateHeaders(); +- + synchronized (output) { + output.headersEnd(streamId); + diff -Nru tomcat10-10.1.6/debian/patches/series tomcat10-10.1.6/debian/patches/series --- tomcat10-10.1.6/debian/patches/series 2023-10-10 16:33:08.000000000 +0000 +++ tomcat10-10.1.6/debian/patches/series 2024-04-10 21:06:29.000000000 +0000 @@ -17,3 +17,6 @@ CVE-2023-42795.patch CVE-2023-44487.patch CVE-2023-45648.patch +CVE-2024-24549.patch +CVE-2024-23672.patch +CVE-2023-46589.patch