diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 950b22f067..9216944e51 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -848,14 +848,16 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) return journal_file_fstat(f); } -static int journal_file_move_to( +static int journal_file_move_to_full( JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, - void **ret) { + void **ret, + uint64_t *ret_size) { + size_t window_size; int r; assert(f); @@ -884,7 +886,27 @@ static int journal_file_move_to( return -EADDRNOTAVAIL; } - return mmap_cache_fd_get(f->cache_fd, type_to_category(type), keep_always, offset, size, &f->last_stat, ret); + r = mmap_cache_fd_get(f->cache_fd, type_to_category(type), keep_always, offset, size, &f->last_stat, ret, &window_size); + if (r < 0) + return r; + + /* The window is rounded up to whole pages, and may extend beyond the end of the file, which must not + * be accessed */ + if (ret_size) + *ret_size = MIN((uint64_t) window_size, (uint64_t) f->last_stat.st_size - offset); + + return 0; +} + +static int journal_file_move_to( + JournalFile *f, + ObjectType type, + bool keep_always, + uint64_t offset, + uint64_t size, + void **ret) { + + return journal_file_move_to_full(f, type, keep_always, offset, size, ret, /* ret_size= */ NULL); } static uint64_t minimum_header_size(JournalFile *f, Object *o) { @@ -1106,8 +1128,9 @@ static int check_object(JournalFile *f, Object *o, uint64_t offset) { } int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) { - int r; + uint64_t size, available; Object *o; + int r; assert(f); @@ -1129,7 +1152,7 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset journal_object_type_to_string(type), offset); - r = journal_file_move_to(f, type, false, offset, offsetof(ObjectHeader, payload), (void**) &o); + r = journal_file_move_to_full(f, type, false, offset, offsetof(ObjectHeader, payload), (void**) &o, &available); if (r < 0) return r; @@ -1137,13 +1160,17 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset if (r < 0) return r; - r = journal_file_move_to(f, type, false, offset, le64toh(READ_NOW(o->object.size)), (void**) &o); - if (r < 0) - return r; + /* Usually the window of the header contains the whole object, which then needs no second lookup */ + size = le64toh(READ_NOW(o->object.size)); + if (size > available) { + r = journal_file_move_to(f, type, false, offset, size, (void**) &o); + if (r < 0) + return r; - r = check_object_header(f, o, type, offset); - if (r < 0) - return r; + r = check_object_header(f, o, type, offset); + if (r < 0) + return r; + } r = check_object(f, o, offset); if (r < 0) @@ -4249,7 +4276,7 @@ int journal_file_open( goto fail; } - r = mmap_cache_fd_get(f->cache_fd, MMAP_CACHE_CATEGORY_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h); + r = mmap_cache_fd_get(f->cache_fd, MMAP_CACHE_CATEGORY_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, /* ret_size= */ NULL); if (r == -EINVAL) { /* Some file systems (jffs2 or p9fs) don't support mmap() properly (or only read-only * mmap()), and return EINVAL in that case. Let's propagate that as a more recognizable error diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c index 79061940b3..d0a7c9eeaf 100644 --- a/src/libsystemd/sd-journal/journal-verify.c +++ b/src/libsystemd/sd-journal/journal-verify.c @@ -404,7 +404,7 @@ static int contains_uint64(MMapFileDescriptor *f, uint64_t n, uint64_t p) { c = (a + b) / 2; - r = mmap_cache_fd_get(f, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z); + r = mmap_cache_fd_get(f, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, /* ret_size= */ NULL); if (r < 0) return r; diff --git a/src/libsystemd/sd-journal/mmap-cache.c b/src/libsystemd/sd-journal/mmap-cache.c index f49ca12ba4..58d52ff41e 100644 --- a/src/libsystemd/sd-journal/mmap-cache.c +++ b/src/libsystemd/sd-journal/mmap-cache.c @@ -342,7 +342,8 @@ int mmap_cache_fd_get( uint64_t offset, size_t size, struct stat *st, - void **ret) { + void **ret, + size_t *ret_size) { MMapCache *m = mmap_cache_fd_cache(f); Window *w; @@ -386,6 +387,8 @@ found: category_attach_window(m, c, w); *ret = (uint8_t*) w->ptr + (offset - w->offset); + if (ret_size) + *ret_size = w->offset + w->size - offset; return 0; } diff --git a/src/libsystemd/sd-journal/mmap-cache.h b/src/libsystemd/sd-journal/mmap-cache.h index bf690536e9..24f492076e 100644 --- a/src/libsystemd/sd-journal/mmap-cache.h +++ b/src/libsystemd/sd-journal/mmap-cache.h @@ -39,7 +39,8 @@ int mmap_cache_fd_get( uint64_t offset, size_t size, struct stat *st, - void **ret); + void **ret, + size_t *ret_size); int mmap_cache_fd_pin( MMapFileDescriptor *f, diff --git a/src/libsystemd/sd-journal/test-mmap-cache.c b/src/libsystemd/sd-journal/test-mmap-cache.c index b59d5177f6..9fae3dcaa5 100644 --- a/src/libsystemd/sd-journal/test-mmap-cache.c +++ b/src/libsystemd/sd-journal/test-mmap-cache.c @@ -14,6 +14,7 @@ int main(int argc, char *argv[]) { char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX"; MMapCache *m; void *p, *q; + size_t sp, sq; test_setup_logging(LOG_DEBUG); @@ -30,21 +31,26 @@ int main(int argc, char *argv[]) { ASSERT_OK(z = mkostemp_safe(pz)); (void) unlink(pz); - ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 1, 2, NULL, &p)); + ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 1, 2, NULL, &p, &sp)); + ASSERT_GE(sp, 2U); - ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 2, 2, NULL, &q)); + ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 2, 2, NULL, &q, &sq)); ASSERT_PTR_EQ((uint8_t*) p + 1, (uint8_t*) q); + ASSERT_EQ(sq, sp - 1); - ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 3, 2, NULL, &q)); + ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 3, 2, NULL, &q, &sq)); ASSERT_PTR_EQ((uint8_t*) p + 2, (uint8_t*) q); + ASSERT_EQ(sq, sp - 2); - ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p)); + ASSERT_OK(mmap_cache_fd_get(fx, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p, &sp)); + ASSERT_GE(sp, 2U); - ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q)); + ASSERT_OK(mmap_cache_fd_get(fx, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q, &sq)); ASSERT_PTR_EQ((uint8_t*) p + 1, (uint8_t*) q); + ASSERT_EQ(sq, sp - 1); mmap_cache_fd_free(fx); mmap_cache_unref(m);