dovecot-2.2: zlib: Fixed copying causing cache corruption when z...

dovecot at dovecot.org dovecot at dovecot.org
Fri Nov 27 12:57:30 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/574c1e5b3d90
changeset: 19427:574c1e5b3d90
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Nov 27 14:57:03 2015 +0200
description:
zlib: Fixed copying causing cache corruption when zlib_save wasn't set.
dovecot.index.cache entries were broken/missing if:
- The zlib plugin is enabled;
- The zlib_save/zlib_save_level options are NOT enabled;
- The source message being copied is compressed;
- The mail_log plugin is logging "copy" events;
- The mail_log_fields setting includes at least one message header;
- The destination mailbox folder has an index file that is recording the
logged headers;
- The source mailbox folder does NOT have an index file recording the
logged headers.

Found by Robert L Mathews.

diffstat:

 src/plugins/zlib/zlib-plugin.c |  40 +++++++++++++++++++++++++---------------
 1 files changed, 25 insertions(+), 15 deletions(-)

diffs (99 lines):

diff -r 2ddbdf05b19b -r 574c1e5b3d90 src/plugins/zlib/zlib-plugin.c
--- a/src/plugins/zlib/zlib-plugin.c	Fri Nov 27 14:42:43 2015 +0200
+++ b/src/plugins/zlib/zlib-plugin.c	Fri Nov 27 14:57:03 2015 +0200
@@ -26,6 +26,11 @@
 #define MAX_INBUF_SIZE (1024*1024)
 #define ZLIB_MAIL_CACHE_EXPIRE_MSECS (60*1000)
 
+struct zlib_mail {
+	union mail_module_context module_ctx;
+	bool verifying_save;
+};
+
 struct zlib_transaction_context {
 	union mailbox_transaction_module_context module_ctx;
 
@@ -112,16 +117,15 @@
 	struct zlib_user *zuser = ZLIB_USER_CONTEXT(_mail->box->storage->user);
 	struct zlib_mail_cache *cache = &zuser->cache;
 	struct mail_private *mail = (struct mail_private *)_mail;
-	union mail_module_context *zmail = ZLIB_MAIL_CONTEXT(mail);
+	struct zlib_mail *zmail = ZLIB_MAIL_CONTEXT(mail);
 	struct istream *input;
 	const struct compression_handler *handler;
 
-	/* don't uncompress input when we are reading a mail that we're just
-	   in the middle of saving, and we didn't do the compression ourself.
-	   in such situation we're probably checking if the user-given input
-	   looks compressed */
-	if (_mail->saving && zuser->save_handler == NULL)
-		return zmail->super.istream_opened(_mail, stream);
+	if (zmail->verifying_save) {
+		/* zlib_mail_save_finish() is verifying that the user-given
+		   input doesn't look compressed. */
+		return zmail->module_ctx.super.istream_opened(_mail, stream);
+	}
 
 	if (cache->uid == _mail->uid && cache->box == _mail->box) {
 		/* use the cached stream. when doing partial reads it should
@@ -129,7 +133,7 @@
 		i_stream_unref(stream);
 		i_stream_seek(cache->input, 0);
 		*stream = i_stream_create_limit(cache->input, (uoff_t)-1);
-		return zmail->super.istream_opened(_mail, stream);
+		return zmail->module_ctx.super.istream_opened(_mail, stream);
 	}
 
 	handler = compression_detect_handler(*stream);
@@ -147,7 +151,7 @@
 
 		*stream = zlib_mail_cache_open(zuser, _mail, *stream);
 	}
-	return zmail->super.istream_opened(_mail, stream);
+	return zmail->module_ctx.super.istream_opened(_mail, stream);
 }
 
 static void zlib_mail_allocated(struct mail *_mail)
@@ -155,17 +159,17 @@
 	struct zlib_transaction_context *zt = ZLIB_CONTEXT(_mail->transaction);
 	struct mail_private *mail = (struct mail_private *)_mail;
 	struct mail_vfuncs *v = mail->vlast;
-	union mail_module_context *zmail;
+	struct zlib_mail *zmail;
 
 	if (zt == NULL)
 		return;
 
-	zmail = p_new(mail->pool, union mail_module_context, 1);
-	zmail->super = *v;
-	mail->vlast = &zmail->super;
+	zmail = p_new(mail->pool, struct zlib_mail, 1);
+	zmail->module_ctx.super = *v;
+	mail->vlast = &zmail->module_ctx.super;
 
 	v->istream_opened = zlib_istream_opened;
-	MODULE_CONTEXT_SET_SELF(mail, zlib_mail_module, zmail);
+	MODULE_CONTEXT_SET(mail, zlib_mail_module, zmail);
 }
 
 static struct mailbox_transaction_context *
@@ -235,12 +239,18 @@
 {
 	struct mailbox *box = ctx->transaction->box;
 	union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
+	struct mail_private *mail = (struct mail_private *)ctx->dest_mail;
+	struct zlib_mail *zmail = ZLIB_MAIL_CONTEXT(mail);
 	struct istream *input;
+	int ret;
 
 	if (zbox->super.save_finish(ctx) < 0)
 		return -1;
 
-	if (mail_get_stream(ctx->dest_mail, NULL, NULL, &input) < 0)
+	zmail->verifying_save = TRUE;
+	ret = mail_get_stream(ctx->dest_mail, NULL, NULL, &input);
+	zmail->verifying_save = FALSE;
+	if (ret < 0)
 		return -1;
 
 	if (compression_detect_handler(input) != NULL) {


More information about the dovecot-cvs mailing list