Blame SOURCES/dovecot-2.3.13-CVE_2020_24386-part4.patch

27f02a
From 1a27cfa8e337b7e3298ba230059e766cdbc1123d Mon Sep 17 00:00:00 2001
27f02a
From: Timo Sirainen <timo.sirainen@open-xchange.com>
27f02a
Date: Mon, 24 Aug 2020 19:10:43 +0300
27f02a
Subject: [PATCH] imap: imap_client_hibernate() - Return reason string on
27f02a
 failure
27f02a
27f02a
This helps writing a unit test for it.
27f02a
---
27f02a
 src/imap/cmd-idle.c              |  3 ++-
27f02a
 src/imap/imap-client-hibernate.c | 10 +++++++++-
27f02a
 src/imap/imap-client.h           |  5 +++--
27f02a
 3 files changed, 14 insertions(+), 4 deletions(-)
27f02a
27f02a
diff --git a/src/imap/cmd-idle.c b/src/imap/cmd-idle.c
27f02a
index 8a05582d03..2b31dc714e 100644
27f02a
--- a/src/imap/cmd-idle.c
27f02a
+++ b/src/imap/cmd-idle.c
27f02a
@@ -175,11 +175,12 @@ static void idle_add_keepalive_timeout(struct cmd_idle_context *ctx)
27f02a
 static void idle_hibernate_timeout(struct cmd_idle_context *ctx)
27f02a
 {
27f02a
 	struct client *client = ctx->client;
27f02a
+	const char *reason;
27f02a
 
27f02a
 	i_assert(ctx->sync_ctx == NULL);
27f02a
 	i_assert(!ctx->sync_pending);
27f02a
 
27f02a
-	if (imap_client_hibernate(&client)) {
27f02a
+	if (imap_client_hibernate(&client, &reason)) {
27f02a
 		/* client may be destroyed now */
27f02a
 	} else {
27f02a
 		/* failed - don't bother retrying */
27f02a
diff --git a/src/imap/imap-client-hibernate.c b/src/imap/imap-client-hibernate.c
27f02a
index d3451b1bf6..0709e4a244 100644
27f02a
--- a/src/imap/imap-client-hibernate.c
27f02a
+++ b/src/imap/imap-client-hibernate.c
27f02a
@@ -203,19 +203,23 @@ imap_hibernate_process_send(struct client *client, const buffer_t *state,
27f02a
 	return 0;
27f02a
 }
27f02a
 
27f02a
-bool imap_client_hibernate(struct client **_client)
27f02a
+bool imap_client_hibernate(struct client **_client, const char **reason_r)
27f02a
 {
27f02a
 	struct client *client = *_client;
27f02a
 	buffer_t *state;
27f02a
 	const char *error;
27f02a
 	int ret, fd_notify = -1, fd_hibernate = -1;
27f02a
 
27f02a
+	*reason_r = NULL;
27f02a
+
27f02a
 	if (client->fd_in != client->fd_out) {
27f02a
 		/* we won't try to hibernate stdio clients */
27f02a
+		*reason_r = "stdio clients can't be hibernated";
27f02a
 		return FALSE;
27f02a
 	}
27f02a
 	if (o_stream_get_buffer_used_size(client->output) > 0) {
27f02a
 		/* wait until we've sent the pending output to client */
27f02a
+		*reason_r = "output pending to client";
27f02a
 		return FALSE;
27f02a
 	}
27f02a
 
27f02a
@@ -233,11 +237,13 @@ bool imap_client_hibernate(struct client **_client)
27f02a
 			"Couldn't export state: %s (mailbox=%s)", error,
27f02a
 			client->mailbox == NULL ? "" :
27f02a
 			mailbox_get_vname(client->mailbox));
27f02a
+		*reason_r = error;
27f02a
 	} else if (ret == 0) {
27f02a
 		e_debug(client->event, "Couldn't hibernate imap client: "
27f02a
 			"Couldn't export state: %s (mailbox=%s)", error,
27f02a
 			client->mailbox == NULL ? "" :
27f02a
 			mailbox_get_vname(client->mailbox));
27f02a
+		*reason_r = error;
27f02a
 	}
27f02a
 	if (ret > 0 && client->mailbox != NULL) {
27f02a
 		fd_notify = mailbox_watch_extract_notify_fd(client->mailbox,
27f02a
@@ -248,6 +254,7 @@ bool imap_client_hibernate(struct client **_client)
27f02a
 			e_debug(client->event, "Couldn't hibernate imap client: "
27f02a
 				"Couldn't extract notifications fd: %s",
27f02a
 				error);
27f02a
+			*reason_r = error;
27f02a
 			ret = -1;
27f02a
 		}
27f02a
 	}
27f02a
@@ -257,5 +264,6 @@ bool imap_client_hibernate(struct client **_client)
27f02a
 			e_error(client->event,
27f02a
 				"Couldn't hibernate imap client: %s", error);
27f02a
+			*reason_r = error;
27f02a
 			ret = -1;
27f02a
 		}
27f02a
 	}
27f02a
diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h
27f02a
index f2ffe0d7c9..4e591d5c7c 100644
27f02a
--- a/src/imap/imap-client.h
27f02a
+++ b/src/imap/imap-client.h
27f02a
@@ -323,8 +323,9 @@ enum mailbox_feature client_enabled_mailbox_features(struct client *client);
27f02a
 const char *const *client_enabled_features(struct client *client);
27f02a
 
27f02a
 /* Send client processing to imap-idle process. If successful, returns TRUE
27f02a
-   and destroys the client. */
27f02a
-bool imap_client_hibernate(struct client **client);
27f02a
+   and destroys the client. If hibernation failed, the exact reason is
27f02a
+   returned (mainly for unit tests). */
27f02a
+bool imap_client_hibernate(struct client **client, const char **reason_r);
27f02a
 
27f02a
 struct imap_search_update *
27f02a
 client_search_update_lookup(struct client *client, const char *tag,