dovecot-2.2: doveadm dump: Avoid crashes with corrupted log files

dovecot at dovecot.org dovecot at dovecot.org
Mon Jun 16 13:27:34 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/d6882dfa08d7
changeset: 17499:d6882dfa08d7
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jun 16 16:26:09 2014 +0300
description:
doveadm dump: Avoid crashes with corrupted log files

diffstat:

 src/doveadm/doveadm-dump-log.c |  38 +++++++++++++++++++++++++++++---------
 1 files changed, 29 insertions(+), 9 deletions(-)

diffs (94 lines):

diff -r b2e16f0e88db -r d6882dfa08d7 src/doveadm/doveadm-dump-log.c
--- a/src/doveadm/doveadm-dump-log.c	Mon Jun 16 15:47:12 2014 +0300
+++ b/src/doveadm/doveadm-dump-log.c	Mon Jun 16 16:26:09 2014 +0300
@@ -214,12 +214,18 @@
 	HDRF(day_stamp)
 };
 
-static void log_header_update(const struct mail_transaction_header_update *u)
+static void log_header_update(const struct mail_transaction_header_update *u,
+			      size_t data_size)
 {
 	const void *data = u + 1;
 	unsigned int offset = u->offset, size = u->size;
 	unsigned int i;
 
+	if (sizeof(*u) + size > data_size) {
+		printf(" - offset = %u, size = %u (too large)\n", offset, size);
+		return;
+	}
+
 	while (size > 0) {
 		/* don't bother trying to handle header updates that include
 		   unknown/unexpected fields offsets/sizes */
@@ -247,7 +253,8 @@
 }
 
 static void log_record_print(const struct mail_transaction_header *hdr,
-			     const void *data, uint64_t *modseq)
+			     const void *data, size_t data_size,
+			     uint64_t *modseq)
 {
 	unsigned int size = hdr->size - sizeof(*hdr);
 
@@ -297,7 +304,7 @@
 	case MAIL_TRANSACTION_HEADER_UPDATE: {
 		const struct mail_transaction_header_update *u = data;
 
-		log_header_update(u);
+		log_header_update(u, data_size);
 		break;
 	}
 	case MAIL_TRANSACTION_EXT_INTRO: {
@@ -331,16 +338,26 @@
 	case MAIL_TRANSACTION_EXT_HDR_UPDATE: {
 		const struct mail_transaction_ext_hdr_update *u = data;
 
-		printf(" - offset = %u, size = %u: ", u->offset, u->size);
-		print_data(u + 1, u->size);
+		printf(" - offset = %u, size = %u", u->offset, u->size);
+		if (sizeof(*u) + u->size <= data_size) {
+			printf(": ");
+			print_data(u + 1, u->size);
+		} else {
+			printf(" (too large)");
+		}
 		printf("\n");
 		break;
 	}
 	case MAIL_TRANSACTION_EXT_HDR_UPDATE32: {
 		const struct mail_transaction_ext_hdr_update32 *u = data;
 
-		printf(" - offset = %u, size = %u: ", u->offset, u->size);
-		print_data(u + 1, u->size);
+		printf(" - offset = %u, size = %u", u->offset, u->size);
+		if (sizeof(*u) + u->size <= data_size) {
+			printf(": ");
+			print_data(u + 1, u->size);
+		} else {
+			printf(" (too large)");
+		}
 		printf("\n");
 		break;
 	}
@@ -352,7 +369,10 @@
 		record_size = (sizeof(*rec) + prev_intro.record_size + 3) & ~3;
 		while (rec < end) {
 			printf(" - uid=%u: ", rec->uid);
-			print_data(rec + 1, prev_intro.record_size);
+			if (prev_intro.record_size <= (char*)end - (char *)(rec+1))
+				print_data(rec + 1, prev_intro.record_size);
+			else
+				printf("(record_size too large)");
 			printf("\n");
 			rec = CONST_PTR_OFFSET(rec, record_size);
 		}
@@ -507,7 +527,7 @@
 			i_fatal("rec data read() %"PRIuSIZE_T" != %"PRIuSIZE_T,
 				ret, hdr.size - sizeof(hdr));
 		}
-		log_record_print(&hdr, buf, modseq);
+		log_record_print(&hdr, buf, (size_t)ret, modseq);
 	} else {
 		if (lseek(fd, hdr.size - sizeof(hdr), SEEK_CUR) < 0)
 			i_fatal("lseek() failed: %m");


More information about the dovecot-cvs mailing list