summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2013-05-13 17:40:01 +0200
committerTomas Bzatek <tbzatek@redhat.com>2013-05-13 17:40:01 +0200
commit21811b3ae17ec705327484c1ce0be75fec95bb0e (patch)
tree22025ad077d5702483a8c8d5c6900773a140bb2f
parent6b12c3d7b33c87a7fea228106f39ecf2a3e0f310 (diff)
metadata: Be more resistive to broken journal files
In shared NFS homedir case with multiple clients writing to the same mmaped journal file data can get easily corrupted. The daemon iterates over a journal file on flush taking in account variable entry size and advances according to the data read. However in certain case invalid data are read making us to jump out of bounds. In case of zero entry size we would stand at the same place leading to infinite loop. This patch checks if the indicated entry size is at least the size of the structure we're getting the size from (it's a first element) and breaks the iteration cycle if it's not. This may lead to partial data loss on flush as we don't process the rest of the journal file. Old data from existing tree file will be preserved of course, only few recent changes would get lost. https://bugzilla.gnome.org/show_bug.cgi?id=637095
-rw-r--r--metadata/metatree.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/metadata/metatree.c b/metadata/metatree.c
index 015300eb..20b78627 100644
--- a/metadata/metatree.c
+++ b/metadata/metatree.c
@@ -1304,6 +1304,11 @@ meta_journal_iterate (MetaJournal *journal,
{
sizep = (guint32 *)entry;
entry = (MetaJournalEntry *)((char *)entry - GUINT32_FROM_BE (*(sizep-1)));
+ if (GUINT32_FROM_BE (*(sizep)) < sizeof (MetaJournalEntry) && entry > journal->first_entry)
+ {
+ g_warning ("meta_journal_iterate: found short sized entry, possible journal corruption\n");
+ break;
+ }
mtime = GUINT64_FROM_BE (entry->mtime);
journal_path = &entry->path[0];
@@ -2343,6 +2348,13 @@ apply_journal_to_builder (MetaTree *tree,
sizep = (guint32 *)entry;
entry = (MetaJournalEntry *)((char *)entry + GUINT32_FROM_BE (*(sizep)));
+ if (GUINT32_FROM_BE (*(sizep)) < sizeof (MetaJournalEntry) && entry < journal->last_entry)
+ {
+ /* This shouldn't happen, we found an entry that is shorter than its data */
+ /* See https://bugzilla.gnome.org/show_bug.cgi?id=637095 for discussion */
+ g_warning ("apply_journal_to_builder: found short sized entry, possible journal corruption\n");
+ break;
+ }
}
}