Fix CVE-2026-42006: bypass of CVE-2026-27857 IMAP parser fix

Backport upstream commit 9a0f8c1066956ea7450ca82b57f904332006a502
to fix CVE-2026-42006. The IMAP parser's list_count_limit was
incorrectly checking the limit in imap_parser_close_list() (on
')') instead of imap_parser_open_list() (on '('). This patch
moves the check so it correctly limits the number of open
braces, preventing potential abuse via deeply nested lists.

CVE: CVE-2026-42006
Upstream patches:
 - 9a0f8c1066.patch
Resolves: RHEL-188480

This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.

Assisted-by: Ymir
This commit is contained in:
RHEL Packaging Agent 2026-06-26 11:28:05 +00:00
parent b199fd1c0d
commit cb203ee7f1
2 changed files with 111 additions and 1 deletions

View File

@ -0,0 +1,101 @@
From 73983fb8e62e93d06c2563f33d268937c7fa4164 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 27 Apr 2026 17:40:46 +0300
Subject: [PATCH] lib-imap: Fix imap_parser_params.list_count_limit to actually
work
The previous fix in d0f67b52914565a35f3817335ab9633cb291513c was
accidentally limiting the number of ')', not the number of '('.
---
src/lib-imap/imap-parser.c | 19 +++++++++++--------
src/lib-imap/test-imap-parser.c | 14 ++++++++++++--
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index 20fe7bf..3cd87ab 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -191,8 +191,15 @@ static struct imap_arg *imap_arg_create(struct imap_parser *parser)
return arg;
}
-static void imap_parser_open_list(struct imap_parser *parser)
+static bool imap_parser_open_list(struct imap_parser *parser)
{
+ if (parser->list_count >= parser->list_count_limit) {
+ parser->error_msg = "Too many '('";
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
+ return FALSE;
+ }
+ parser->list_count++;
+
parser->list_arg = imap_arg_create(parser);
parser->list_arg->type = IMAP_ARG_LIST;
p_array_init(&parser->list_arg->_data.list, parser->pool,
@@ -200,6 +207,7 @@ static void imap_parser_open_list(struct imap_parser *parser)
parser->cur_list = &parser->list_arg->_data.list;
parser->cur_type = ARG_PARSE_NONE;
+ return TRUE;
}
static bool imap_parser_close_list(struct imap_parser *parser)
@@ -217,12 +225,6 @@ static bool imap_parser_close_list(struct imap_parser *parser)
parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
return FALSE;
}
- if (parser->list_count >= parser->list_count_limit) {
- parser->error_msg = "Too many '('";
- parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
- return FALSE;
- }
- parser->list_count++;
arg = imap_arg_create(parser);
arg->type = IMAP_ARG_EOL;
@@ -673,7 +675,8 @@ static bool imap_parser_read_arg(struct imap_parser *parser)
parser->literal8 = FALSE;
break;
case '(':
- imap_parser_open_list(parser);
+ if (!imap_parser_open_list(parser))
+ return FALSE;
if ((parser->flags & IMAP_PARSE_FLAG_STOP_AT_LIST) != 0) {
i_stream_skip(parser->input, 1);
return FALSE;
diff --git a/src/lib-imap/test-imap-parser.c b/src/lib-imap/test-imap-parser.c
index 0767cfb..cd6bcdd 100644
--- a/src/lib-imap/test-imap-parser.c
+++ b/src/lib-imap/test-imap-parser.c
@@ -85,9 +85,15 @@ static void test_imap_parser_list_limit(void)
struct {
const char *input;
int ret;
+ const char *error;
} tests[] = {
- { "(())\r\n", 1 },
- { "((()))\r\n", -1 },
+ { "(())\r\n", 1, NULL },
+ { "((\r\n", -1, "Missing ')'" },
+ { "(()\r\n", -1, "Missing ')'" },
+ { "(()))\r\n", -1, "Unexpected ')'" },
+ { "((()))\r\n", -1, "Too many '('" },
+ { "(({10}\r\n", -2, NULL },
+ { "((({10}\r\n", -1, "Too many '('" },
};
struct istream_chain *chain;
struct istream *chain_input;
@@ -112,6 +118,10 @@ static void test_imap_parser_list_limit(void)
(void)i_stream_read(chain_input);
test_assert_cmp(imap_parser_read_args(parser, 0, 0, &args), ==, tests[i].ret);
+ if (tests[i].ret == -1) {
+ enum imap_parser_error err;
+ test_assert_strcmp_idx(imap_parser_get_error(parser, &err), tests[i].error, i);
+ }
/* skip over CRLF */
i_stream_skip(chain_input, i_stream_get_data_size(chain_input));
--
2.52.0

View File

@ -5,7 +5,7 @@ Name: dovecot
Epoch: 1
Version: 2.3.16
%global prever %{nil}
Release: 7%{?dist}
Release: 8%{?dist}
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
License: MIT and LGPLv2
Group: System Environment/Daemons
@ -88,6 +88,10 @@ Patch29: dovecot-2.3-cve-2026-27857p4of5.patch
# https://github.com/dovecot/pigeonhole/commit/5701db04455ee4d8e927d0b225634780a9b656b4
Patch30: dovecot-2.3-cve-2026-27857p5of5.patch
# from upstream for < 2.4.4, RHEL-188480
# https://github.com/dovecot/core/commit/9a0f8c1066956ea7450ca82b57f904332006a502
Patch31: dovecot-2.3-cve-2026-42006.patch
Source15: prestartscript
BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel
@ -212,6 +216,7 @@ mv dovecot-2.3-pigeonhole-%{pigeonholever} dovecot-pigeonhole
%patch -P 28 -p1 -b .cve-2026-27857p3of5
%patch -P 29 -p1 -b .cve-2026-27857p4of5
%patch -P 30 -p1 -b .cve-2026-27857p5of5
%patch -P 31 -p1 -b .cve-2026-42006
sed -i '/DEFAULT_INCLUDES *=/s|$| '"$(pkg-config --cflags libclucene-core)|" src/plugins/fts-lucene/Makefile.in
@ -572,6 +577,10 @@ make check
%{_libdir}/%{name}/dict/libdriver_pgsql.so
%changelog
* Fri Jun 26 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 1:2.3.16-8
- fix CVE-2026-42006: fix IMAP parser list_count_limit to correctly
limit open braces instead of close braces (RHEL-188480)
* Mon Apr 13 2026 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.16-7
- fix CVE-2026-27858: denial of service via crafted message before authentication (RHEL-161630)
- fix CVE-2025-59032: ManageSieve: Denial of Service via crafted SASL initial response in AUTHENTICATE command (RHEL-162282)