From 7c15f8745cd721d387393c890dc3e7154a7e0467 Mon Sep 17 00:00:00 2001 From: shixuantong Date: Sat, 22 Feb 2025 09:04:28 +0800 Subject: [PATCH] fix CVE-2025-25186 (cherry picked from commit 9d1564fe1e9cd5db7988e1bd4a6a902a930e16b8) --- backport-CVE-2025-25186.patch | 123 ++++++++++++++++++++++++++++++++++ ruby.spec | 6 +- 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2025-25186.patch diff --git a/backport-CVE-2025-25186.patch b/backport-CVE-2025-25186.patch new file mode 100644 index 0000000..3912210 --- /dev/null +++ b/backport-CVE-2025-25186.patch @@ -0,0 +1,123 @@ +From 0dbb8eb72aa78b7ed0b01533388e69722d16b821 Mon Sep 17 00:00:00 2001 +From: nick evans +Date: Wed, 8 Jan 2025 22:06:47 -0500 +Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=94=92=20Prevent=20runaway=20memory?= + =?UTF-8?q?=20use=20when=20parsing=20uid-set?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reference:https://github.com/ruby/net-imap/commit/0dbb8eb72aa78b7ed0b01533388e69722d16b821 +Conflict:not change test, the test/net/imap/ directory doesn't exist. + +Problem +========= + +The UID sets in UIDPlusData are stored as arrays of UIDs. In common +scenarios, copying between one and a few hundred emails at a time, this +is barely noticable. But the memory use expands _exponentially_. + +This should not be an issue for _trusted_ servers, and (I assume) +compromised servers will be more interested in evading detection and +stealing your credentials and your email than in causing client Denial +of Service. Nevertheless, this is a very simple DoS attack against +clients connecting to untrusted servers (for example, a service that +connects to user-specified servers). + +For example, assuming a 64-bit architecture, considering only the data +in the two arrays, assuming the arrays' internal capacity is no more +than needed, and ignoring the fixed cost of the response structs: +* 32 bytes expands to ~160KB (about 5000 times more): + `"* OK [COPYUID 1 1:9999 1:9999]\r\n"` +* 40 bytes expands to ~1.6GB (about 50 million times more): + `"* OK [COPYUID 1 1:99999999 1:99999999]\r\n"` +* In the worst scenario (uint32 max), 44 bytes expands to 64GiB in + memory, using over 1.5 billion times more to store than to send: + `"* OK [COPYUID 1 1:4294967295 1:4294967295]\r\n"` + +Preferred fix +=============== + +The preferred fix is to store `uid-set` as a SequenceSet, not an array. +Unfortunately, this is not fully backwards compatible. For v0.4 and +v0.5, use `Config#parser_use_deprecated_uidplus_data` to false to use +AppendUIDData and CopyUIDData instead of UIDPlusData. Unless you are +_using_ UIDPLUS, this is completely safe. v0.6 will drop UIDPlusData. + +Workaround +============ + +The simplest _partial_ fix (preserving full backward compatibility) is +to raise an error when the number of UIDs goes over some threshold, and +continue using arrays inside UIDPlusData. + +For v0.3 (this commit) the maximum count is hard-coded to 10,000. This +is high enough that it should almost never be triggered by normal usage, +and low enough to be a less extreme problem. For v0.4 and v0.5, the +maximum array size is configurable, with a much lower default: 1000 for +v0.4 and 100 for v0.5. These are low enough that they are _unlikely_ to +cause a problem, but v0.4 and v0.5 can also use the newer AppendUIDData +and CopyUIDData classes. + +However, because unhandled responses are stored on the `#responses` +hash, this can still be a problem. A malicious server could repeatedly +use 160Kb of client memory by sending only 32 bytes in a loop. To fully +solve this problem, a response handler must be added to prune excessive +APPENDUID/COPYUID responses as they are received. + +Because unhandled responses have always been retained, managing +unhandled responses is already documented as necessary for long-lived +connections. +--- + .../lib/net/imap/response_parser.rb | 26 ++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/.bundle/gems/net-imap-0.3.4/lib/net/imap/response_parser.rb b/.bundle/gems/net-imap-0.3.4/lib/net/imap/response_parser.rb +index be1a849..0341356 100644 +--- a/.bundle/gems/net-imap-0.3.4/lib/net/imap/response_parser.rb ++++ b/.bundle/gems/net-imap-0.3.4/lib/net/imap/response_parser.rb +@@ -7,6 +7,8 @@ module Net + + # Parses an \IMAP server response. + class ResponseParser ++ MAX_UID_SET_SIZE = 10_000 ++ + # :call-seq: Net::IMAP::ResponseParser.new -> Net::IMAP::ResponseParser + def initialize + @str = nil +@@ -1379,11 +1381,29 @@ module Net + case token.symbol + when T_NUMBER then [Integer(token.value)] + when T_ATOM +- token.value.split(",").flat_map {|range| +- range = range.split(":").map {|uniqueid| Integer(uniqueid) } +- range.size == 1 ? range : Range.new(range.min, range.max).to_a ++ entries = uid_set__ranges(token.value) ++ if (count = entries.sum(&:count)) > MAX_UID_SET_SIZE ++ parse_error("uid-set is too large: %d > 10k", count) ++ end ++ entries.flat_map(&:to_a) ++ end ++ end ++ ++ # returns an array of ranges ++ def uid_set__ranges(uidset) ++ entries = [] ++ uidset.split(",") do |entry| ++ uids = entry.split(":", 2).map {|uid| ++ unless uid =~ /\A[1-9][0-9]*\z/ ++ parse_error("invalid uid-set uid: %p", uid) ++ end ++ uid = Integer(uid) ++ NumValidator.ensure_nz_number(uid) ++ uid + } ++ entries << Range.new(*uids.minmax) + end ++ entries + end + + def nil_atom +-- +2.27.0 + diff --git a/ruby.spec b/ruby.spec index 01fc1bc..f49a482 100644 --- a/ruby.spec +++ b/ruby.spec @@ -33,7 +33,7 @@ Name: ruby Version: %{ruby_version} -Release: 147 +Release: 148 Summary: Object-oriented scripting language interpreter License: (Ruby or BSD) and Public Domain and MIT and CC0 and zlib and UCD URL: https://www.ruby-lang.org/en/ @@ -103,6 +103,7 @@ Patch6026: backport-CVE-2024-39908-CVE-2024-41123-upgrade-lib-rexml-to-3.3.3.pat Patch6027: backport-CVE-2024-43398-upgrade-lib-rexml-to-3.3.6.patch Patch6028: backport-CVE-2024-47220.patch Patch6029: backport-CVE-2024-49761.patch +Patch6030: backport-CVE-2025-25186.patch Provides: %{name}-libs = %{version}-%{release} Obsoletes: %{name}-libs < %{version}-%{release} @@ -888,6 +889,9 @@ make runruby TESTRUN_SCRIPT=%{SOURCE13} %{gem_dir}/specifications/matrix-%{matrix_version}.gemspec %changelog +* Sat Feb 22 2025 shixuantong - 3.2.2-148 +- fix CVE-2025-25186 + * Tue Oct 29 2024 shixuantong - 3.2.2-147 - fix CVE-2024-49761 -- Gitee