[dovecot-cvs] dovecot: Added more corruption detection code.

dovecot at dovecot.org dovecot at dovecot.org
Wed Jun 13 21:35:18 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/18d7a680ffae
changeset: 5721:18d7a680ffae
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Jun 13 21:35:14 2007 +0300
description:
Added more corruption detection code.

diffstat:

2 files changed, 54 insertions(+), 10 deletions(-)
src/lib-index/mail-index-sync-update.c    |   37 ++++++++++++++++++++++-------
src/lib-index/mail-transaction-log-view.c |   27 +++++++++++++++++++--

diffs (136 lines):

diff -r 5f4a7e932c4f -r 18d7a680ffae src/lib-index/mail-index-sync-update.c
--- a/src/lib-index/mail-index-sync-update.c	Wed Jun 13 21:34:16 2007 +0300
+++ b/src/lib-index/mail-index-sync-update.c	Wed Jun 13 21:35:14 2007 +0300
@@ -593,7 +593,7 @@ int mail_index_sync_record(struct mail_i
 			rec = CONST_PTR_OFFSET(data, i);
 			if (i + sizeof(*rec) + rec->name_size > hdr->size) {
 				mail_index_sync_set_corrupted(ctx,
-					"extension intro: name_size too large");
+					"ext intro: name_size too large");
 				ret = -1;
 				break;
 			}
@@ -610,6 +610,13 @@ int mail_index_sync_record(struct mail_i
 	}
 	case MAIL_TRANSACTION_EXT_RESET: {
 		const struct mail_transaction_ext_reset *rec = data;
+
+		if (hdr->size != sizeof(*rec)) {
+			mail_index_sync_set_corrupted(ctx,
+				"ext reset: invalid record size");
+			ret = -1;
+			break;
+		}
 		ret = mail_index_sync_ext_reset(ctx, rec);
 		break;
 	}
@@ -619,6 +626,15 @@ int mail_index_sync_record(struct mail_i
 
 		for (i = 0; i < hdr->size; ) {
 			rec = CONST_PTR_OFFSET(data, i);
+
+			if (i + sizeof(*rec) > hdr->size ||
+			    i + sizeof(*rec) + rec->size > hdr->size) {
+				mail_index_sync_set_corrupted(ctx,
+					"ext hdr update: invalid record size");
+				ret = -1;
+				break;
+			}
+
 			ret = mail_index_sync_ext_hdr_update(ctx, rec);
 			if (ret <= 0)
 				break;
@@ -630,9 +646,9 @@ int mail_index_sync_record(struct mail_i
 		break;
 	}
 	case MAIL_TRANSACTION_EXT_REC_UPDATE: {
-		const struct mail_transaction_ext_rec_update *rec, *end;
+		const struct mail_transaction_ext_rec_update *rec;
 		const struct mail_index_ext *ext;
-		unsigned int record_size;
+		unsigned int i, record_size;
 
 		if (ctx->cur_ext_id == (uint32_t)-1) {
 			mail_index_sync_set_corrupted(ctx,
@@ -651,14 +667,19 @@ int mail_index_sync_record(struct mail_i
 		/* the record is padded to 32bits in the transaction log */
 		record_size = (sizeof(*rec) + ext->record_size + 3) & ~3;
 
-		rec = data;
-		end = CONST_PTR_OFFSET(data, hdr->size);
-		while (rec < end) {
+		for (i = 0; i < hdr->size; i += record_size) {
+			rec = CONST_PTR_OFFSET(data, i);
+
+			if (i + record_size > hdr->size) {
+				mail_index_sync_set_corrupted(ctx,
+					"ext rec update: invalid record size");
+				ret = -1;
+				break;
+			}
+
 			ret = mail_index_sync_ext_rec_update(ctx, rec);
 			if (ret <= 0)
 				break;
-
-			rec = CONST_PTR_OFFSET(rec, record_size);
 		}
 		break;
 	}
diff -r 5f4a7e932c4f -r 18d7a680ffae src/lib-index/mail-transaction-log-view.c
--- a/src/lib-index/mail-transaction-log-view.c	Wed Jun 13 21:34:16 2007 +0300
+++ b/src/lib-index/mail-transaction-log-view.c	Wed Jun 13 21:35:14 2007 +0300
@@ -349,12 +349,25 @@ log_view_is_record_valid(struct mail_tra
 		return FALSE;
 	}
 
+	if (rec_size == 0) {
+		mail_transaction_log_file_set_corrupted(file,
+			"Empty record contents (type=0x%x)", rec_type);
+		return FALSE;
+	}
+
 	/* records that are exported by syncing and view syncing will be
 	   checked here so that we don't have to implement the same validation
 	   multiple times. other records are checked internally by
 	   mail_index_sync_record(). */
 	t_push();
 	switch (rec_type) {
+	case MAIL_TRANSACTION_APPEND:
+		if ((rec_size % sizeof(struct mail_index_record)) != 0) {
+			mail_transaction_log_file_set_corrupted(file,
+				"Invalid append record size");
+			ret = FALSE;
+		}
+		break;
 	case MAIL_TRANSACTION_EXPUNGE:
 		uid_buf = buffer_create_const_data(pool_datastack_create(),
 						   data, rec_size);
@@ -375,8 +388,7 @@ log_view_is_record_valid(struct mail_tra
 		if ((seqset_offset % 4) != 0)
 			seqset_offset += 4 - (seqset_offset % 4);
 
-		if (seqset_offset >= rec_size ||
-		    ((rec_size - seqset_offset) % (sizeof(uint32_t)*2)) != 0) {
+		if (seqset_offset > rec_size) {
 			mail_transaction_log_file_set_corrupted(file,
 				"Invalid keyword update record size");
 			ret = FALSE;
@@ -402,6 +414,17 @@ log_view_is_record_valid(struct mail_tra
 	if (array_is_created(&uids)) {
 		const struct seq_range *rec, *prev = NULL;
 		unsigned int i, count = array_count(&uids);
+
+		if ((uid_buf->used % uids.arr.element_size) != 0) {
+			mail_transaction_log_file_set_corrupted(file,
+				"Invalid record size (type=0x%x)", rec_type);
+			ret = FALSE;
+			count = 0;
+		} else if (count == 0) {
+			mail_transaction_log_file_set_corrupted(file,
+				"No UID ranges (type=0x%x)", rec_type);
+			ret = FALSE;
+		}
 
 		for (i = 0; i < count; i++, prev = rec) {
 			rec = array_idx(&uids, i);


More information about the dovecot-cvs mailing list