dovecot-2.2: lib-index: Fixes to handling broken cache records t...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 16 18:57:45 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/99b7be36631b
changeset: 15792:99b7be36631b
user: Timo Sirainen <tss at iki.fi>
date: Tue Jan 22 16:53:52 2013 +0200
description:
lib-index: Fixes to handling broken cache records that point outside file.
Especially try to avoid failing by trying to allocate gigabytes of memory.
diffstat:
src/lib-index/mail-cache-lookup.c | 13 ++++++-------
src/lib-index/mail-cache.c | 19 +++++++++++++++++--
2 files changed, 23 insertions(+), 9 deletions(-)
diffs (76 lines):
diff -r 2b76d357a56a -r 99b7be36631b src/lib-index/mail-cache-lookup.c
--- a/src/lib-index/mail-cache-lookup.c Tue Jan 22 16:31:17 2013 +0200
+++ b/src/lib-index/mail-cache-lookup.c Tue Jan 22 16:53:52 2013 +0200
@@ -15,6 +15,7 @@
{
const struct mail_cache_record *rec;
const void *data;
+ int ret;
i_assert(offset != 0);
@@ -41,17 +42,15 @@
}
if (rec->size > CACHE_PREFETCH) {
/* larger than we guessed. map the rest of the record. */
- if (mail_cache_map(cache, offset, rec->size, &data) < 0)
+ if ((ret = mail_cache_map(cache, offset, rec->size, &data)) < 0)
return -1;
+ if (ret == 0) {
+ mail_cache_set_corrupted(cache, "record points outside file");
+ return -1;
+ }
rec = data;
}
- if (rec->size > cache->mmap_length ||
- offset + rec->size > cache->mmap_length) {
- mail_cache_set_corrupted(cache, "record points outside file");
- return -1;
- }
-
*rec_r = rec;
return 0;
}
diff -r 2b76d357a56a -r 99b7be36631b src/lib-index/mail-cache.c
--- a/src/lib-index/mail-cache.c Tue Jan 22 16:31:17 2013 +0200
+++ b/src/lib-index/mail-cache.c Tue Jan 22 16:53:52 2013 +0200
@@ -357,12 +357,28 @@
int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size,
const void **data_r)
{
+ struct stat st;
const void *data;
ssize_t ret;
if (size == 0)
size = sizeof(struct mail_cache_header);
+ /* verify offset + size before trying to allocate a huge amount of
+ memory due to them. note that we may be prefetching more than we
+ actually need, so don't fail too early. */
+ if (size > cache->mmap_length || offset + size > cache->mmap_length) {
+ if (fstat(cache->fd, &st) < 0) {
+ i_error("fstat(%s) failed: %m", cache->filepath);
+ return -1;
+ }
+ if (offset >= (uoff_t)st.st_size) {
+ *data_r = NULL;
+ return 0;
+ }
+ size = st.st_size - offset;
+ }
+
cache->remap_counter++;
if (cache->map_with_read)
return mail_cache_map_with_read(cache, offset, size, data_r);
@@ -451,8 +467,7 @@
mail_cache_init_file_cache(cache);
- if (mail_cache_map(cache, 0, sizeof(struct mail_cache_header),
- &data) < 0)
+ if (mail_cache_map(cache, 0, 0, &data) < 0)
return -1;
return 1;
}
More information about the dovecot-cvs
mailing list