Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package tomcat for openSUSE:Factory checked in at 2022-11-22 16:10:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/tomcat (Old) and /work/SRC/openSUSE:Factory/.tomcat.new.1597 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tomcat" Tue Nov 22 16:10:22 2022 rev:87 rq:1037218 version:9.0.43 Changes: -------- --- /work/SRC/openSUSE:Factory/tomcat/tomcat.changes 2022-07-14 16:34:48.076658751 +0200 +++ /work/SRC/openSUSE:Factory/.tomcat.new.1597/tomcat.changes 2022-11-22 16:10:28.226117504 +0100 @@ -1,0 +2,16 @@ +Mon Nov 21 07:42:34 UTC 2022 - Michele Bussolotto <michele.bussolo...@suse.com> + +- Fixed CVEs: + * CVE-2022-42252: reject invalid content-length requests. (bsc#1204918) +- Added patches: + * tomcat-9.0.43-CVE-2022-42252.patch + +------------------------------------------------------------------- +Thu Oct 20 15:58:40 UTC 2022 - Michele Bussolotto <michele.bussolo...@suse.com> + +- Fixed CVEs: + * CVE-2021-43980: Improve the recycling of Processor objects to make it more robust. (bsc#1203868) +- Added patches: + * tomcat-9.0.43-CVE-2021-43980.patch + +------------------------------------------------------------------- New: ---- tomcat-9.0.43-CVE-2021-43980.patch tomcat-9.0.43-CVE-2022-42252.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tomcat.spec ++++++ --- /var/tmp/diff_new_pack.9ZJBEh/_old 2022-11-22 16:10:29.174122314 +0100 +++ /var/tmp/diff_new_pack.9ZJBEh/_new 2022-11-22 16:10:29.182122354 +0100 @@ -88,6 +88,8 @@ Patch10: tomcat-9.0-NPE-JNDIRealm.patch Patch11: tomcat-9.0-CVE-2022-23181.patch Patch12: tomcat-9.0-hardening_getResources.patch +Patch13: tomcat-9.0.43-CVE-2021-43980.patch +Patch14: tomcat-9.0.43-CVE-2022-42252.patch BuildRequires: ant >= 1.8.1 BuildRequires: ant-antlr @@ -266,6 +268,8 @@ %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 # remove date from docs sed -i -e '/build-date/ d' webapps/docs/tomcat-docs.xsl ++++++ tomcat-9.0.43-CVE-2021-43980.patch ++++++ >From 170e0f792bd18ff031677890ba2fe50eb7a376c1 Mon Sep 17 00:00:00 2001 From: Mark Thomas <ma...@apache.org> Date: Tue, 29 Mar 2022 19:15:37 +0100 Subject: [PATCH] Improve the recycling of Processor objects to make it more robust. --- java/org/apache/coyote/AbstractProtocol.java | 32 ++++++++++--------- .../tomcat/util/net/SocketWrapperBase.java | 17 +++++++--- webapps/docs/changelog.xml | 4 +++ 3 files changed, 33 insertions(+), 20 deletions(-) Index: apache-tomcat-9.0.43-src/java/org/apache/coyote/AbstractProtocol.java =================================================================== --- apache-tomcat-9.0.43-src.orig/java/org/apache/coyote/AbstractProtocol.java +++ apache-tomcat-9.0.43-src/java/org/apache/coyote/AbstractProtocol.java @@ -794,7 +794,11 @@ public abstract class AbstractProtocol<S S socket = wrapper.getSocket(); - Processor processor = (Processor) wrapper.getCurrentProcessor(); + // We take complete ownership of the Processor inside of this method to ensure + // no other thread can release it while we're using it. Whatever processor is + // held by this variable will be associated with the SocketWrapper before this + // method returns. + Processor processor = (Processor) wrapper.takeCurrentProcessor(); if (getLog().isDebugEnabled()) { getLog().debug(sm.getString("abstractConnectionHandler.connectionsGet", processor, socket)); @@ -879,9 +883,6 @@ public abstract class AbstractProtocol<S processor.setSslSupport( wrapper.getSslSupport(getProtocol().getClientCertProvider())); - // Associate the processor with the connection - wrapper.setCurrentProcessor(processor); - SocketState state = SocketState.CLOSED; do { state = processor.process(wrapper, status); @@ -901,8 +902,6 @@ public abstract class AbstractProtocol<S release(processor); // Create the upgrade processor processor = upgradeProtocol.getProcessor(wrapper, getProtocol().getAdapter()); - // Associate with the processor with the connection - wrapper.setCurrentProcessor(processor); } else { if (getLog().isDebugEnabled()) { getLog().debug(sm.getString( @@ -922,8 +921,6 @@ public abstract class AbstractProtocol<S getLog().debug(sm.getString("abstractConnectionHandler.upgradeCreate", processor, wrapper)); } - // Associate with the processor with the connection - wrapper.setCurrentProcessor(processor); // Initialise the upgrade handler (which may trigger // some IO using the new protocol which is why the lines // above are necessary) @@ -961,8 +958,8 @@ public abstract class AbstractProtocol<S } else if (state == SocketState.OPEN) { // In keep-alive but between requests. OK to recycle // processor. Continue to poll for the next request. - wrapper.setCurrentProcessor(null); release(processor); + processor = null; wrapper.registerReadInterest(); } else if (state == SocketState.SENDFILE) { // Sendfile in progress. If it fails, the socket will be @@ -987,8 +984,7 @@ public abstract class AbstractProtocol<S // Connection closed. OK to recycle the processor. // Processors handling upgrades require additional clean-up // before release. - wrapper.setCurrentProcessor(null); - if (processor.isUpgrade()) { + if (processor != null && processor.isUpgrade()) { UpgradeToken upgradeToken = processor.getUpgradeToken(); HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler(); InstanceManager instanceManager = upgradeToken.getInstanceManager(); @@ -1009,7 +1005,13 @@ public abstract class AbstractProtocol<S } } } + release(processor); + processor = null; + } + + if (processor != null) { + wrapper.setCurrentProcessor(processor); } return state; } catch(java.net.SocketException e) { @@ -1047,7 +1049,6 @@ public abstract class AbstractProtocol<S // Make sure socket/processor is removed from the list of current // connections - wrapper.setCurrentProcessor(null); release(processor); return SocketState.CLOSED; } @@ -1081,7 +1082,9 @@ public abstract class AbstractProtocol<S /** * Expected to be used by the handler once the processor is no longer - * required. + * required. Care must be taken to ensure that this method is only + * called once per processor, after the request processing has + * completed. * * @param processor Processor being released (that was associated with * the socket) @@ -1119,8 +1122,7 @@ public abstract class AbstractProtocol<S */ @Override public void release(SocketWrapperBase<S> socketWrapper) { - Processor processor = (Processor) socketWrapper.getCurrentProcessor(); - socketWrapper.setCurrentProcessor(null); + Processor processor = (Processor) socketWrapper.takeCurrentProcessor(); release(processor); } Index: apache-tomcat-9.0.43-src/java/org/apache/tomcat/util/net/SocketWrapperBase.java =================================================================== --- apache-tomcat-9.0.43-src.orig/java/org/apache/tomcat/util/net/SocketWrapperBase.java +++ apache-tomcat-9.0.43-src/java/org/apache/tomcat/util/net/SocketWrapperBase.java @@ -29,6 +29,7 @@ import java.util.concurrent.RejectedExec import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -104,10 +105,12 @@ public abstract class SocketWrapperBase< protected volatile OperationState<?> writeOperation = null; /** - * The org.apache.coyote.Processor instance currently associated - * with the wrapper. + * The org.apache.coyote.Processor instance currently associated with the + * wrapper. Only populated when required to maintain wrapper<->Processor + * mapping between calls to + * {@link AbstractEndpoint.Handler#process(SocketWrapperBase, SocketEvent)}. */ - protected Object currentProcessor = null; + private final AtomicReference<Object> currentProcessor = new AtomicReference<>(); public SocketWrapperBase(E socket, AbstractEndpoint<E,?> endpoint) { this.socket = socket; @@ -134,11 +137,15 @@ public abstract class SocketWrapperBase< } public Object getCurrentProcessor() { - return currentProcessor; + return currentProcessor.get(); } public void setCurrentProcessor(Object currentProcessor) { - this.currentProcessor = currentProcessor; + this.currentProcessor.set(currentProcessor); + } + + public Object takeCurrentProcessor() { + return currentProcessor.getAndSet(null); } /** Index: apache-tomcat-9.0.43-src/webapps/docs/changelog.xml =================================================================== --- apache-tomcat-9.0.43-src.orig/webapps/docs/changelog.xml +++ apache-tomcat-9.0.43-src/webapps/docs/changelog.xml @@ -485,6 +485,10 @@ Fix a concurrency issue in the NIO connector that could cause newly created connections to be removed from the poller. (markt) </fix> + <fix> + Improve the recycling of Processor objects to make it more robust. + (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> ++++++ tomcat-9.0.43-CVE-2022-42252.patch ++++++ >From 4c7f4fd09d2cc1692112ef70b8ee23a7a037ae77 Mon Sep 17 00:00:00 2001 From: Mark Thomas <ma...@apache.org> Date: Mon, 3 Oct 2022 11:59:01 +0100 Subject: [PATCH] Requests with invalid content-length should always be rejected --- Index: apache-tomcat-9.0.43-src/java/org/apache/coyote/http11/Http11InputBuffer.java =================================================================== --- apache-tomcat-9.0.43-src.orig/java/org/apache/coyote/http11/Http11InputBuffer.java +++ apache-tomcat-9.0.43-src/java/org/apache/coyote/http11/Http11InputBuffer.java @@ -886,7 +886,7 @@ public class Http11InputBuffer implement headerData.lastSignificantChar = pos; byteBuffer.position(byteBuffer.position() - 1); // skipLine() will handle the error - return skipLine(); + return skipLine(false); } // chr is next byte of header name. Convert to lowercase. @@ -897,7 +897,7 @@ public class Http11InputBuffer implement // Skip the line and ignore the header if (headerParsePos == HeaderParsePosition.HEADER_SKIPLINE) { - return skipLine(); + return skipLine(false); } // @@ -948,15 +948,11 @@ public class Http11InputBuffer implement } else if (prevChr == Constants.CR && chr == Constants.LF) { eol = true; } else if (prevChr == Constants.CR) { - // Invalid value - // Delete the header (it will be the most recent one) - headers.removeHeader(headers.size() - 1); - return skipLine(); + // Invalid value - also need to delete header + return skipLine(true); } else if (chr != Constants.HT && HttpParser.isControl(chr)) { - // Invalid value - // Delete the header (it will be the most recent one) - headers.removeHeader(headers.size() - 1); - return skipLine(); + // Invalid value - also need to delete header + return skipLine(true); } else if (chr == Constants.SP || chr == Constants.HT) { byteBuffer.put(headerData.realPos, chr); headerData.realPos++; @@ -1004,7 +1000,27 @@ public class Http11InputBuffer implement } - private HeaderParseStatus skipLine() throws IOException { + private HeaderParseStatus skipLine(boolean deleteHeader) throws IOException { + boolean rejectThisHeader = rejectIllegalHeader; + // Check if rejectIllegalHeader is disabled and needs to be overridden + // for this header. The header name is required to determine if this + // override is required. The header name is only available once the + // header has been created. If the header has been created then + // deleteHeader will be true. + if (!rejectThisHeader && deleteHeader) { + if (headers.getName(headers.size() - 1).equalsIgnoreCase("content-length")) { + // Malformed content-length headers must always be rejected + // RFC 9112, section 6.3, bullet 5. + rejectThisHeader = true; + } else { + // Only need to delete the header if the request isn't going to + // be rejected (it will be the most recent one) + headers.removeHeader(headers.size() - 1); + } + } + + // Parse the rest of the invalid header so we can construct a useful + // exception and/or debug message. headerParsePos = HeaderParsePosition.HEADER_SKIPLINE; boolean eol = false; @@ -1029,11 +1045,11 @@ public class Http11InputBuffer implement headerData.lastSignificantChar = pos; } } - if (rejectIllegalHeader || log.isDebugEnabled()) { + if (rejectThisHeader || log.isDebugEnabled()) { String message = sm.getString("iib.invalidheader", HeaderUtil.toPrintableString(byteBuffer.array(), headerData.lineStart, headerData.lastSignificantChar - headerData.lineStart + 1)); - if (rejectIllegalHeader) { + if (rejectThisHeader) { throw new IllegalArgumentException(message); } log.debug(message); Index: apache-tomcat-9.0.43-src/webapps/docs/changelog.xml =================================================================== --- apache-tomcat-9.0.43-src.orig/webapps/docs/changelog.xml +++ apache-tomcat-9.0.43-src/webapps/docs/changelog.xml @@ -223,6 +223,11 @@ Avoid possible infinite loop in <code>OpenSSLEngine.unwrap</code> when the destination buffers state is changed concurrently. (remm) </fix> + <fix> + Enforce the requirement of RFC 7230 onwards that a request with a + malformed <code>content-length</code> header should always be rejected + with a 400 response. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper">