diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-12-28 19:33:23 -0500 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2014-01-11 10:07:22 -0500 |
commit | ae97089d49d1795a35a443b7b830ee666028e733 (patch) | |
tree | 528eab7122f5a7b4bb0cf1ad220164b3c0438323 /src/journal/sd-journal.c | |
parent | 47917e4a4a8f1ee00bb7de3e83f7bfd849abf337 (diff) |
journal: fix access to munmapped memory in sd_journal_enumerate_unique
sd_j_e_u needs to keep a reference to an object while comparing it
with possibly duplicate objects in other files. Because the size of
mmap cache is limited, with enough files and object to compare to,
at some point the object being compared would be munmapped, resulting
in a segmentation fault.
Fix this issue by turning keep_always into a reference count that can
be increased and decreased. Other callers which set keep_always=true
are unmodified: their references are never released but are ignored
when the whole file is closed, which happens at some point. keep_always
is increased in sd_j_e_u and later on released.
Diffstat (limited to 'src/journal/sd-journal.c')
-rw-r--r-- | src/journal/sd-journal.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 283d593063..7466006752 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2481,9 +2481,7 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { } _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { - Object *o; size_t k; - int r; assert_return(j, -EINVAL); assert_return(!journal_pid_changed(j), -ECHILD); @@ -2503,9 +2501,11 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ for (;;) { JournalFile *of; Iterator i; + Object *o; const void *odata; size_t ol; bool found; + int r; /* Proceed to next data object in the field's linked list */ if (j->unique_offset == 0) { @@ -2542,8 +2542,16 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ return r; /* Let's do the type check by hand, since we used 0 context above. */ - if (o->object.type != OBJECT_DATA) + if (o->object.type != OBJECT_DATA) { + log_error("%s:offset " OFSfmt ": object has type %d, expected %d", + j->unique_file->path, j->unique_offset, + o->object.type, OBJECT_DATA); return -EBADMSG; + } + + r = journal_file_object_keep(j->unique_file, o, j->unique_offset); + if (r < 0) + return r; r = return_data(j, j->unique_file, o, &odata, &ol); if (r < 0) @@ -2577,6 +2585,10 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ if (found) continue; + r = journal_file_object_release(j->unique_file, o, j->unique_offset); + if (r < 0) + return r; + r = return_data(j, j->unique_file, o, data, l); if (r < 0) return r; |