Moderate severityNVD Advisory· Published Nov 12, 2024· Updated Nov 13, 2024
Denial of Service attack on windows app using Netty
CVE-2024-47535
Description
Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. An unsafe reading of environment file could potentially cause a denial of service in Netty. When loaded on an Windows application, Netty attempts to load a file that does not exist. If an attacker creates such a large file, the Netty application crashes. This vulnerability is fixed in 4.1.115.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
io.netty:netty-commonMaven | < 4.1.115.Final | 4.1.115.Final |
Affected products
1Patches
15 files changed · +142 −10
common/src/main/java/io/netty/util/internal/BoundedInputStream.java+83 −0 added@@ -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; + } +}
common/src/main/java/io/netty/util/internal/PlatformDependent.java+2 −3 modified@@ -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) {
common/src/main/java/io/netty/util/NetUtil.java+5 −3 modified@@ -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();
common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java+44 −0 added@@ -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(); + } +}
resolver-dns/src/main/java/io/netty/resolver/dns/ResolvConf.java+8 −4 modified@@ -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(); } }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-xq3w-v528-46rvghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-47535ghsaADVISORY
- github.com/netty/netty/commit/fbf7a704a82e7449b48bd0bbb679f5661c6d61a3ghsax_refsource_MISCWEB
- github.com/netty/netty/security/advisories/GHSA-xq3w-v528-46rvghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.