OK.

On 2025-10-31 12:37 p.m., Stuart Henderson wrote:
There are a few crash fixes, etc, in Dovecot's release-2.3 branch,
https://github.com/dovecot/core/tree/release-2.3

According to https://marc.info/?l=dovecot&m=176191803628624&w=2 they
won't be making another 'community edition' release from there unless
there's a security issue (I guess these were mostly done for commercial
users) so this cherry-picks them as patches to the port. I skipped the
"add variables holding local/remote port numbers for mail_log_prefix"
commits. Also adds commit info for the existing replicator-queue.c fix.

ok?

Index: Makefile
===================================================================
RCS file: /cvs/ports/mail/dovecot/Makefile,v
diff -u -p -r1.321 Makefile
--- Makefile    21 Jul 2025 16:51:21 -0000      1.321
+++ Makefile    31 Oct 2025 16:21:33 -0000
@@ -11,8 +11,7 @@ COMMENT-postgresql= PostgreSQL authentic
  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}
Index: patches/patch-src_doveadm_doveadm-mail-save_c
===================================================================
RCS file: patches/patch-src_doveadm_doveadm-mail-save_c
diff -N patches/patch-src_doveadm_doveadm-mail-save_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_doveadm_doveadm-mail-save_c       31 Oct 2025 16:21:33 
-0000
@@ -0,0 +1,22 @@
+From 97791e1ea53fdff64bafef6ff572b237b41dbe3b Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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;
+ }
+
Index: patches/patch-src_imap-login_imap-login-cmd-id_c
===================================================================
RCS file: patches/patch-src_imap-login_imap-login-cmd-id_c
diff -N patches/patch-src_imap-login_imap-login-cmd-id_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_imap-login_imap-login-cmd-id_c    31 Oct 2025 16:21:33 
-0000
@@ -0,0 +1,37 @@
+From 1fd4fcc00335a0560e5686e17aceece7933f214d Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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 }
+ };
Index: patches/patch-src_imap_cmd-idle_c
===================================================================
RCS file: patches/patch-src_imap_cmd-idle_c
diff -N patches/patch-src_imap_cmd-idle_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_imap_cmd-idle_c   31 Oct 2025 16:21:33 -0000
@@ -0,0 +1,32 @@
+From 9a00369c8a09ccb2799dd6b3a4767947f5ace55a Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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);
+ }
Index: patches/patch-src_lib-storage_index_dbox-multi_mdbox-map_c
===================================================================
RCS file: patches/patch-src_lib-storage_index_dbox-multi_mdbox-map_c
diff -N patches/patch-src_lib-storage_index_dbox-multi_mdbox-map_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_lib-storage_index_dbox-multi_mdbox-map_c  31 Oct 2025 
16:21:33 -0000
@@ -0,0 +1,21 @@
+From efdceaab8aa8c2443264b5cc2239e19c72904227 Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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)
Index: patches/patch-src_lib_istream-seekable_c
===================================================================
RCS file: patches/patch-src_lib_istream-seekable_c
diff -N patches/patch-src_lib_istream-seekable_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_lib_istream-seekable_c    31 Oct 2025 16:21:33 -0000
@@ -0,0 +1,157 @@
+From 30b7e3cb5c7037a5a2d31096a75696d70c9c9f94 Mon Sep 17 00:00:00 2001
+From: Markus Valentin <[email protected]>
+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 <[email protected]>
+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 <[email protected]>
+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 <[email protected]>
+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 <[email protected]>
+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 <[email protected]>
+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);
Index: patches/patch-src_plugins_fts_fts-storage_c
===================================================================
RCS file: patches/patch-src_plugins_fts_fts-storage_c
diff -N patches/patch-src_plugins_fts_fts-storage_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_plugins_fts_fts-storage_c 31 Oct 2025 16:21:33 -0000
@@ -0,0 +1,18 @@
+From 13061d620c1dd6952bbb7b0d4a7ae4f5e665b8d9 Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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;
Index: patches/patch-src_plugins_virtual_virtual-mail_c
===================================================================
RCS file: patches/patch-src_plugins_virtual_virtual-mail_c
diff -N patches/patch-src_plugins_virtual_virtual-mail_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_plugins_virtual_virtual-mail_c    31 Oct 2025 16:21:33 
-0000
@@ -0,0 +1,21 @@
+From 4eb23fdf2d285d710dc1f70b5158dbc6ffef48aa Mon Sep 17 00:00:00 2001
+From: Timo Sirainen <[email protected]>
+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
Index: patches/patch-src_replication_replicator_replicator-queue_c
===================================================================
RCS file: 
/cvs/ports/mail/dovecot/patches/patch-src_replication_replicator_replicator-queue_c,v
diff -u -p -r1.1 patch-src_replication_replicator_replicator-queue_c
--- patches/patch-src_replication_replicator_replicator-queue_c 5 Oct 2024 
07:35:54 -0000       1.1
+++ patches/patch-src_replication_replicator_replicator-queue_c 31 Oct 2025 
16:21:33 -0000
@@ -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" <[email protected]>
+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


Reply via email to