since there are not likely to be more dovecot 2.3 releases unless there's

a security fix, cherry-pick everything important-looking from their
2.3-release branch. includes various crash fixes etc. also update the
comment in replicator-queue.c as it was committed upstream.

ok Brad (maintainer)
This commit is contained in:
sthen
2025-10-31 18:41:36 +00:00
parent bb93d9d8b7
commit fe0722e890
9 changed files with 316 additions and 4 deletions
+1 -2
View File
@@ -11,8 +11,7 @@ COMMENT-postgresql= PostgreSQL authentication / dictionary support for Dovecot
V_MAJOR= 2.3
V_DOVECOT= 2.3.21.1
EPOCH= 0
REVISION= 1
REVISION-postgresql= 2
REVISION= 3
DISTNAME= dovecot-${V_DOVECOT}
PKGNAME= dovecot-${V_DOVECOT}
@@ -0,0 +1,22 @@
From 97791e1ea53fdff64bafef6ff572b237b41dbe3b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 22:46:51 +0300
Subject: [PATCH] doveadm save: Fix potential assert-crash if saving failed
The input stream may not have been fully read at failure time.
Fixes:
Panic: file doveadm-mail-save.c: line 91 (cmd_save_to_mailbox): assertion failed: (input->eof)
Index: src/doveadm/doveadm-mail-save.c
--- src/doveadm/doveadm-mail-save.c.orig
+++ src/doveadm/doveadm-mail-save.c
@@ -77,7 +77,7 @@ cmd_save_to_mailbox(struct save_cmd_context *ctx, stru
mailbox_save_cancel(&save_ctx);
if (trans != NULL)
mailbox_transaction_rollback(&trans);
- i_assert(input->eof);
+ i_assert(ret < 0 || input->eof);
return ret < 0 ? -1 : 0;
}
@@ -0,0 +1,37 @@
From 1fd4fcc00335a0560e5686e17aceece7933f214d Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Fri, 6 Sep 2024 14:42:55 +0300
Subject: [PATCH] imap-login: Don't forward x-multiplex ID parameter when
proxying
If a connecting v2.4 proxy sends this parameter, it should be ignored rather
than forwarded to the next hop, which again might be v2.4. This would end
up enabling multiplex iostreams, even though this v2.3 proxy doesn't
understand it.
Index: src/imap-login/imap-login-cmd-id.c
--- src/imap-login/imap-login-cmd-id.c.orig
+++ src/imap-login/imap-login-cmd-id.c
@@ -70,6 +70,14 @@ cmd_id_x_forward_(struct imap_client *client,
client_add_forward_field(&client->common, key+10, value);
}
+static void
+cmd_id_x_multiplex(struct imap_client *client ATTR_UNUSED,
+ const char *key ATTR_UNUSED, const char *value ATTR_UNUSED)
+{
+ /* ignore - registered here only so that it's not automatically
+ forwarded by imap_id_retain=yes handling */
+}
+
static const struct imap_id_param_handler imap_login_id_params[] = {
{ "x-originating-ip", FALSE, cmd_id_x_originating_ip },
{ "x-originating-port", FALSE, cmd_id_x_originating_port },
@@ -79,6 +87,7 @@ static const struct imap_id_param_handler imap_login_i
{ "x-session-id", FALSE, cmd_id_x_session_id },
{ "x-session-ext-id", FALSE, cmd_id_x_session_id },
{ "x-forward-", TRUE, cmd_id_x_forward_ },
+ { "x-multiplex", FALSE, cmd_id_x_multiplex },
{ NULL, FALSE, NULL }
};
@@ -0,0 +1,32 @@
From 9a00369c8a09ccb2799dd6b3a4767947f5ace55a Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 14 Oct 2024 12:53:33 +0300
Subject: [PATCH] imap: Fix potential hang/crash when unhibernating
This fixes two potential bugs:
a) Unhibernation is triggered by new mailbox changes. While sending these
to IMAP client, Dovecot notices that the client has disconnected. The
process will stay IDLEing for 30 minutes until it gets disconnected with
"Disconnected: Inactivity - no input for 1800 secs"
b) Unhibernation is triggered by DONE command with some further pipelined
commands. During unhibernation new mailbox changes are noticed, and
again IMAP client is found to be disconnected while sending the changes.
This causes a segfault.
Index: src/imap/cmd-idle.c
--- src/imap/cmd-idle.c.orig
+++ src/imap/cmd-idle.c
@@ -302,7 +302,9 @@ bool cmd_idle(struct client_command_context *cmd)
/* check immediately if there are changes. if they came before we
added mailbox-notifier, we wouldn't see them otherwise. */
- if (client->mailbox != NULL)
- idle_sync_now(client->mailbox, ctx);
+ if (client->mailbox != NULL) {
+ if (idle_sync_now(client->mailbox, ctx))
+ return TRUE;
+ }
return idle_client_handle_input(ctx, FALSE);
}
@@ -0,0 +1,21 @@
From efdceaab8aa8c2443264b5cc2239e19c72904227 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Wed, 20 Nov 2024 15:16:00 +0200
Subject: [PATCH] mdbox: Fix crash if resync fails because of an early failure
This mainly happened if dovecot.map.index.log was locked and resync timed
out waiting for it.
Index: src/lib-storage/index/dbox-multi/mdbox-map.c
--- src/lib-storage/index/dbox-multi/mdbox-map.c.orig
+++ src/lib-storage/index/dbox-multi/mdbox-map.c
@@ -537,7 +537,8 @@ void mdbox_map_atomic_set_success(struct mdbox_map_ato
void mdbox_map_atomic_unset_fscked(struct mdbox_map_atomic_context *atomic)
{
- mail_index_unset_fscked(atomic->sync_trans);
+ if (atomic->sync_trans != NULL)
+ mail_index_unset_fscked(atomic->sync_trans);
}
int mdbox_map_atomic_finish(struct mdbox_map_atomic_context **_atomic)
@@ -0,0 +1,157 @@
From 30b7e3cb5c7037a5a2d31096a75696d70c9c9f94 Mon Sep 17 00:00:00 2001
From: Markus Valentin <markus.valentin@open-xchange.com>
Date: Tue, 3 Dec 2024 14:30:27 +0100
Subject: [PATCH] lib: istream-seekable - Remove unused define BUF_INITIAL_SIZE
From 97791e1ea53fdff64bafef6ff572b237b41dbe3b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 22:46:51 +0300
Subject: [PATCH] doveadm save: Fix potential assert-crash if saving failed
The input stream may not have been fully read at failure time.
From 53c7113720fbf4768f6413fdfbb2e55bc778716d Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 23:05:22 +0300
Subject: [PATCH] lib: istream-seekable - Fix moving stream to memory on
write() failure
Fixes:
Panic: file istream-seekable.c: line 238 (read_from_buffer): assertion failed: (*ret_r > 0)
From 6afc5b06a543c936aa428d758d7f8bad3f13fb66 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 23:23:40 +0300
Subject: [PATCH] lib: istream-seekable - Assert that write() won't return 0
From bc94afb46ad201af6c4a0e145ac07f8730973b01 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 23:28:23 +0300
Subject: [PATCH] lib: istream-seekable - Improve logging after write() errors
Also don't silently handle out of disk space errors - log a warning instead.
From 7fe2c39271b8e993632fd1b9a3ec95e031360f24 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 3 Jun 2024 23:42:25 +0300
Subject: [PATCH] lib: istream-seekable - Allow in-memory fallback only for up
to 10 MB streams
Index: src/lib/istream-seekable.c
--- src/lib/istream-seekable.c.orig
+++ src/lib/istream-seekable.c
@@ -13,13 +13,14 @@
#include <unistd.h>
-#define BUF_INITIAL_SIZE (1024*32)
+#define MAX_MEMORY_FALLBACK_SIZE (1024*1024*10)
struct seekable_istream {
struct istream_private istream;
- char *temp_path;
+ char *temp_path, *write_failed_temp_path;
uoff_t write_peak;
+ int write_failed_errno;
uoff_t size;
size_t buffer_peak;
@@ -63,6 +64,7 @@ static void i_stream_seekable_destroy(struct iostream_
if (sstream->free_context)
i_free(sstream->context);
i_free(sstream->temp_path);
+ i_free(sstream->write_failed_temp_path);
i_free(sstream->input);
}
@@ -194,6 +196,7 @@ static bool read_from_buffer(struct seekable_istream *
/* This could be the first read() or we could have already
seeked backwards. */
i_assert(stream->pos == 0 && stream->skip == 0);
+ i_assert(sstream->buffer_peak >= stream->istream.v_offset);
stream->skip = stream->istream.v_offset;
stream->pos = sstream->buffer_peak;
size = stream->pos - stream->skip;
@@ -244,11 +247,12 @@ static int i_stream_seekable_write_failed(struct seeka
struct istream_private *stream = &sstream->istream;
void *data;
size_t old_pos = stream->pos;
+ int write_errno = errno;
i_assert(sstream->fd != -1);
i_assert(stream->skip == 0);
- stream->max_buffer_size = SIZE_MAX;
+ stream->max_buffer_size = MAX_MEMORY_FALLBACK_SIZE;
stream->pos = 0;
data = i_stream_alloc(stream, sstream->write_peak);
stream->pos = old_pos;
@@ -257,10 +261,11 @@ static int i_stream_seekable_write_failed(struct seeka
sstream->istream.istream.stream_errno = errno;
sstream->istream.istream.eof = TRUE;
io_stream_set_error(&sstream->istream.iostream,
- "istream-seekable: read(%s) failed: %m",
- sstream->temp_path);
+ "istream-seekable: write(%s) failed: %s, and attempt to read() it back failed: %m",
+ sstream->temp_path, strerror(write_errno));
return -1;
}
+ sstream->buffer_peak = sstream->write_peak;
i_stream_destroy(&sstream->fd_input);
sstream->fd = -1; /* autoclosed by fd_input */
@@ -280,6 +285,17 @@ static ssize_t i_stream_seekable_read(struct istream_p
if (read_from_buffer(sstream, &ret))
return ret;
+ if (sstream->write_failed_errno != 0) {
+ errno = sstream->write_failed_errno;
+ sstream->istream.istream.stream_errno = errno;
+ sstream->istream.istream.eof = TRUE;
+ io_stream_set_error(&sstream->istream.iostream,
+ "istream-seekable: write(%s) failed: %m - "
+ "stream is too large for memory",
+ sstream->write_failed_temp_path);
+ return -1;
+ }
+
/* copy everything to temp file and use it as the stream */
if (copy_to_temp_file(sstream) < 0) {
stream->max_buffer_size = SIZE_MAX;
@@ -306,16 +322,31 @@ static ssize_t i_stream_seekable_read(struct istream_p
/* save to our file */
data = i_stream_get_data(sstream->cur_input, &size);
+ i_assert(size > 0);
ret = write(sstream->fd, data, size);
- if (ret <= 0) {
- if (ret < 0 && !ENOSPACE(errno)) {
- i_error("istream-seekable: write_full(%s) failed: %m",
+ i_assert(ret != 0);
+ if (ret < 0) {
+ if (sstream->write_peak + size >= MAX_MEMORY_FALLBACK_SIZE) {
+ sstream->istream.istream.stream_errno = errno;
+ sstream->istream.istream.eof = TRUE;
+ io_stream_set_error(&sstream->istream.iostream,
+ "istream-seekable: write(%s) failed: %m",
sstream->temp_path);
+ return -1;
}
+
+ sstream->write_failed_errno = errno;
+ sstream->write_failed_temp_path =
+ i_strdup(sstream->temp_path);
if (i_stream_seekable_write_failed(sstream) < 0)
return -1;
if (!read_from_buffer(sstream, &ret))
i_unreached();
+
+ errno = sstream->write_failed_errno;
+ i_warning("istream-seekable: write_full(%s) failed: %m - "
+ "fallback to using only memory",
+ sstream->write_failed_temp_path);
return ret;
}
i_stream_sync(sstream->fd_input);
@@ -0,0 +1,18 @@
From 13061d620c1dd6952bbb7b0d4a7ae4f5e665b8d9 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 9 Sep 2024 18:45:59 +0300
Subject: [PATCH] fts: Don't ignore parent mail_precache() failure
Index: src/plugins/fts/fts-storage.c
--- src/plugins/fts/fts-storage.c.orig
+++ src/plugins/fts/fts-storage.c
@@ -558,7 +558,8 @@ static int fts_mail_precache(struct mail *_mail)
struct fts_transaction_context *ft = FTS_CONTEXT_REQUIRE(_mail->transaction);
int ret = 0;
- fmail->module_ctx.super.precache(_mail);
+ if (fmail->module_ctx.super.precache(_mail) < 0)
+ return -1;
if (fmail->virtual_mail) {
if (ft->highest_virtual_uid < _mail->uid)
ft->highest_virtual_uid = _mail->uid;
@@ -0,0 +1,21 @@
From 4eb23fdf2d285d710dc1f70b5158dbc6ffef48aa Mon Sep 17 00:00:00 2001
From: Timo Sirainen <timo.sirainen@open-xchange.com>
Date: Mon, 9 Sep 2024 18:46:56 +0300
Subject: [PATCH] virtual: Fix copying storage error on mail_precache() failure
Index: src/plugins/virtual/virtual-mail.c
--- src/plugins/virtual/virtual-mail.c.orig
+++ src/plugins/virtual/virtual-mail.c
@@ -240,7 +240,11 @@ static int virtual_mail_precache(struct mail *mail)
if (backend_mail_get(vmail, &backend_mail) < 0)
return -1;
p = (struct mail_private *)backend_mail;
- return p->v.precache(backend_mail);
+ if (p->v.precache(backend_mail) < 0) {
+ virtual_box_copy_error(mail->box, backend_mail->box);
+ return -1;
+ }
+ return 0;
}
static void
@@ -1,5 +1,10 @@
replicator: fixed infinity loop on sync replication
https://github.com/dovecot/core/pull/223
From d3a097075afb7b5d8955978ed4a2ae99add11f88 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Wed, 25 Sep 2024 18:30:52 +0200
Subject: [PATCH] replicator: fixed infinity loop on sync replication
Before this fix, replicator adds the same lookup into callbacks over and
over, until it reaches out of memory, and crashes.
Index: src/replication/replicator/replicator-queue.c
--- src/replication/replicator/replicator-queue.c.orig