diff --git a/CVE-2024-47535.patch b/CVE-2024-47535.patch new file mode 100644 index 0000000000000000000000000000000000000000..d094233c8863b0696710178818c127f6fdf29420 --- /dev/null +++ b/CVE-2024-47535.patch @@ -0,0 +1,257 @@ +From fbf7a704a82e7449b48bd0bbb679f5661c6d61a3 Mon Sep 17 00:00:00 2001 +From: Norman Maurer +Date: Tue, 12 Nov 2024 12:08:59 +0100 +Subject: [PATCH] Merge commit from fork + +Motivation: + +We didnt verify the amount of data buffered while reading files / streams during startup which could allow an attacker to cause an OMME if the attacker was able to create a massive file. + +Modifications: + +Decorate InputStream with own that will throw an exception once we reach the limit of data read. + +Result: + +No more risk of OOME +--- + .../src/main/java/io/netty/util/NetUtil.java | 8 +- + .../util/internal/BoundedInputStream.java | 83 +++++++++++++++++++ + .../util/internal/PlatformDependent.java | 5 +- + .../util/internal/BoundedInputStreamTest.java | 44 ++++++++++ + .../io/netty/resolver/dns/ResolvConf.java | 12 ++- + 5 files changed, 142 insertions(+), 10 deletions(-) + create mode 100644 common/src/main/java/io/netty/util/internal/BoundedInputStream.java + create mode 100644 common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java + +diff --git a/common/src/main/java/io/netty/util/NetUtil.java b/common/src/main/java/io/netty/util/NetUtil.java +index c0b454b46299..c28389f05a8a 100644 +--- a/common/src/main/java/io/netty/util/NetUtil.java ++++ b/common/src/main/java/io/netty/util/NetUtil.java +@@ -16,6 +16,7 @@ + package io.netty.util; + + import io.netty.util.NetUtilInitializations.NetworkIfaceAndInetAddress; ++import io.netty.util.internal.BoundedInputStream; + import io.netty.util.internal.PlatformDependent; + import io.netty.util.internal.StringUtil; + import io.netty.util.internal.SystemPropertyUtil; +@@ -24,7 +25,7 @@ + + import java.io.BufferedReader; + import java.io.File; +-import java.io.FileReader; ++import java.io.FileInputStream; + import java.io.IOException; + import java.io.InputStream; + import java.io.InputStreamReader; +@@ -190,7 +191,8 @@ public Integer run() { + // try / catch block. + // See https://github.com/netty/netty/issues/4936 + if (file.exists()) { +- in = new BufferedReader(new FileReader(file)); ++ in = new BufferedReader(new InputStreamReader( ++ new BoundedInputStream(new FileInputStream(file)))); + somaxconn = Integer.parseInt(in.readLine()); + if (logger.isDebugEnabled()) { + logger.debug("{}: {}", file, somaxconn); +@@ -243,7 +245,7 @@ private static Integer sysctlGetInt(String sysctlKey) throws IOException { + try { + // Suppress warnings about resource leaks since the buffered reader is closed below + InputStream is = process.getInputStream(); +- InputStreamReader isr = new InputStreamReader(is); ++ InputStreamReader isr = new InputStreamReader(new BoundedInputStream(is)); + BufferedReader br = new BufferedReader(isr); + try { + String line = br.readLine(); +diff --git a/common/src/main/java/io/netty/util/internal/BoundedInputStream.java b/common/src/main/java/io/netty/util/internal/BoundedInputStream.java +new file mode 100644 +index 000000000000..3062f46905bf +--- /dev/null ++++ b/common/src/main/java/io/netty/util/internal/BoundedInputStream.java +@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2024 The Netty Project ++ * ++ * The Netty Project 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: ++ * ++ * https://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 io.netty.util.internal; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.FilterInputStream; ++import java.io.IOException; ++import java.io.InputStream; ++ ++public final class BoundedInputStream extends FilterInputStream { ++ ++ private final int maxBytesRead; ++ private int numRead; ++ ++ public BoundedInputStream(@NotNull InputStream in, int maxBytesRead) { ++ super(in); ++ this.maxBytesRead = ObjectUtil.checkPositive(maxBytesRead, "maxRead"); ++ } ++ ++ public BoundedInputStream(@NotNull InputStream in) { ++ this(in, 8 * 1024); ++ } ++ ++ @Override ++ public int read() throws IOException { ++ checkMaxBytesRead(1); ++ try { ++ int b = super.read(); ++ if (b <= 0) { ++ // We couldn't read anything. ++ numRead--; ++ } ++ return b; ++ } catch (IOException e) { ++ numRead--; ++ throw e; ++ } ++ } ++ ++ @Override ++ public int read(byte[] buf, int off, int len) throws IOException { ++ // Calculate the maximum number of bytes that we should try to read. ++ int num = Math.min(len, maxBytesRead - numRead + 1); ++ checkMaxBytesRead(num); ++ try { ++ int b = super.read(buf, off, num); ++ if (b == -1) { ++ // We couldn't read anything. ++ numRead -= num; ++ } else if (b != num) { ++ // Correct numRead based on the actual amount we were able to read. ++ numRead -= num - b; ++ } ++ return b; ++ } catch (IOException e) { ++ numRead -= num; ++ throw e; ++ } ++ } ++ ++ private void checkMaxBytesRead(int n) throws IOException { ++ int sum = numRead + n; ++ if (sum < 0 || sum > maxBytesRead) { ++ numRead = maxBytesRead + 1; ++ throw new IOException("Maximum number of bytes read: " + maxBytesRead); ++ } ++ numRead = sum; ++ } ++} +diff --git a/common/src/main/java/io/netty/util/internal/PlatformDependent.java b/common/src/main/java/io/netty/util/internal/PlatformDependent.java +index ae96067e44b3..ed9b313256d0 100644 +--- a/common/src/main/java/io/netty/util/internal/PlatformDependent.java ++++ b/common/src/main/java/io/netty/util/internal/PlatformDependent.java +@@ -239,9 +239,8 @@ public Boolean run() { + if (file.exists()) { + BufferedReader reader = null; + try { +- reader = new BufferedReader( +- new InputStreamReader( +- new FileInputStream(file), CharsetUtil.UTF_8)); ++ reader = new BufferedReader(new InputStreamReader( ++ new BoundedInputStream(new FileInputStream(file)), CharsetUtil.UTF_8)); + + String line; + while ((line = reader.readLine()) != null) { +diff --git a/common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java b/common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java +new file mode 100644 +index 000000000000..35e66e578fcd +--- /dev/null ++++ b/common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java +@@ -0,0 +1,44 @@ ++/* ++ * Copyright 2024 The Netty Project ++ * ++ * The Netty Project 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: ++ * ++ * https://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 io.netty.util.internal; ++ ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.function.Executable; ++ ++import java.io.ByteArrayInputStream; ++import java.io.IOException; ++ ++import static org.junit.jupiter.api.Assertions.assertEquals; ++import static org.junit.jupiter.api.Assertions.assertThrows; ++ ++public class BoundedInputStreamTest { ++ ++ @Test ++ void testBoundEnforced() throws IOException { ++ final byte[] bytes = new byte[64]; ++ PlatformDependent.threadLocalRandom().nextBytes(bytes); ++ final BoundedInputStream reader = new BoundedInputStream(new ByteArrayInputStream(bytes), bytes.length - 1); ++ assertEquals(bytes[0], (byte) reader.read()); ++ ++ assertThrows(IOException.class, new Executable() { ++ @Override ++ public void execute() throws Throwable { ++ reader.read(new byte[64], 0, 64); ++ } ++ }); ++ reader.close(); ++ } ++} +diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java b/resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java +index 0c130c179cc9..1610fb2aa349 100644 +--- a/resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java ++++ b/resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java +@@ -15,9 +15,12 @@ + */ + package io.netty.resolver.dns; + ++import io.netty.util.internal.BoundedInputStream; ++ + import java.io.BufferedReader; +-import java.io.FileReader; ++import java.io.FileInputStream; + import java.io.IOException; ++import java.io.InputStreamReader; + import java.net.InetSocketAddress; + import java.util.ArrayList; + import java.util.Collections; +@@ -45,12 +48,13 @@ static ResolvConf fromReader(BufferedReader reader) throws IOException { + * {@code /etc/resolv.conf} file, see {@code man resolv.conf}. + */ + static ResolvConf fromFile(String file) throws IOException { +- FileReader fileReader = new FileReader(file); ++ BufferedReader reader = new BufferedReader(new InputStreamReader( ++ // Use 1 MB to be a bit conservative ++ new BoundedInputStream(new FileInputStream(file), 1024 * 1024))); + try { +- BufferedReader reader = new BufferedReader(new FileReader(file)); + return fromReader(reader); + } finally { +- fileReader.close(); ++ reader.close(); + } + } + + diff --git a/netty.spec b/netty.spec index 29167d5e609e075d77a292f1f2168eb5538a4c0a..a07ebbe468d6193ae5a3f1029d3630e29786ca6d 100644 --- a/netty.spec +++ b/netty.spec @@ -2,7 +2,7 @@ Name: netty Version: 4.1.13 -Release: 22 +Release: 23 Summary: Asynchronous event-driven network application Java framework License: ASL 2.0 URL: https://netty.io/ @@ -33,6 +33,7 @@ Patch0021: fix-strip.patch # https://github.com/netty/netty/commit/cd91cf3c99123bd1e53fd6a1de0e3d1922f05bb2 Patch0022: CVE-2022-41881.patch Patch0023: CVE-2024-29025.patch +Patch0024: CVE-2024-47535.patch BuildRequires: maven-local mvn(ant-contrib:ant-contrib) BuildRequires: mvn(com.jcraft:jzlib) mvn(commons-logging:commons-logging) @@ -157,6 +158,9 @@ export CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" %changelog +* Wed Nov 13 2024 ZhaoYu Jiang - 4.1.13-23 +- Fix CVE-2024-47535 + * Tue Nov 12 2024 yaoxin - 4.1.13-22 - Fix CVE-2024-29025