1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-23 21:35:11 +03:00

Merge pull request #22350 from poettering/journal-read-object-fix

journal: various fixes to journal_file_read_object()
This commit is contained in:
Yu Watanabe 2022-02-02 13:47:32 +09:00 committed by GitHub
commit 891c9b36cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 17 deletions

View File

@ -23,7 +23,7 @@ static int journald_file_truncate(JournalFile *f) {
int r;
/* truncate excess from the end of archives */
r = journal_file_tail_end(f, &p);
r = journal_file_tail_end_by_pread(f, &p);
if (r < 0)
return log_debug_errno(r, "Failed to determine end of tail object: %m");
@ -45,7 +45,7 @@ static int journald_file_entry_array_punch_hole(JournalFile *f, uint64_t p, uint
return 0;
for (uint64_t q = p; q != 0; q = le64toh(o.entry_array.next_entry_array_offset)) {
r = journal_file_read_object(f, OBJECT_ENTRY_ARRAY, q, &o);
r = journal_file_read_object_header(f, OBJECT_ENTRY_ARRAY, q, &o);
if (r < 0)
return r;
@ -119,7 +119,7 @@ static int journald_file_punch_holes(JournalFile *f) {
for (uint64_t q = le64toh(items[j].head_hash_offset); q != 0;
q = le64toh(o.data.next_hash_offset)) {
r = journal_file_read_object(f, OBJECT_DATA, q, &o);
r = journal_file_read_object_header(f, OBJECT_DATA, q, &o);
if (r < 0) {
log_debug_errno(r, "Invalid data object: %m, ignoring");
break;

View File

@ -91,8 +91,7 @@
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
#endif
int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
Object tail;
int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset) {
uint64_t p;
int r;
@ -100,13 +99,17 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
assert(f->header);
assert(ret_offset);
/* Same as journal_file_tail_end_by_mmap() below, but operates with pread() to avoid the mmap cache
* (and thus is thread safe) */
p = le64toh(f->header->tail_object_offset);
if (p == 0)
p = le64toh(f->header->header_size);
else {
Object tail;
uint64_t sz;
r = journal_file_read_object(f, OBJECT_UNUSED, p, &tail);
r = journal_file_read_object_header(f, OBJECT_UNUSED, p, &tail);
if (r < 0)
return r;
@ -126,6 +129,43 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
return 0;
}
int journal_file_tail_end_by_mmap(JournalFile *f, uint64_t *ret_offset) {
uint64_t p;
int r;
assert(f);
assert(f->header);
assert(ret_offset);
/* Same as journal_file_tail_end_by_pread() above, but operates with the usual mmap logic */
p = le64toh(f->header->tail_object_offset);
if (p == 0)
p = le64toh(f->header->header_size);
else {
Object *tail;
uint64_t sz;
r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
if (r < 0)
return r;
sz = le64toh(READ_NOW(tail->object.size));
if (sz > UINT64_MAX - sizeof(uint64_t) + 1)
return -EBADMSG;
sz = ALIGN64(sz);
if (p > UINT64_MAX - sz)
return -EBADMSG;
p += sz;
}
*ret_offset = p;
return 0;
}
int journal_file_set_offline_thread_join(JournalFile *f) {
int r;
@ -818,10 +858,11 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
return 0;
}
int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
int r;
Object o;
int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret) {
uint64_t s;
ssize_t n;
Object o;
int r;
assert(f);
@ -838,17 +879,22 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O
offset);
/* This will likely read too much data but it avoids having to call pread() twice. */
r = pread(f->fd, &o, sizeof(Object), offset);
if (r < 0)
return r;
n = pread(f->fd, &o, sizeof(o), offset);
if (n < 0)
return log_debug_errno(errno, "Failed to read journal file at offset: %" PRIu64,
offset);
if ((size_t) n < sizeof(o.object))
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Failed to read short object at offset: %" PRIu64,
offset);
s = le64toh(o.object.size);
if (s == 0)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read uninitialized object: %" PRIu64,
offset);
if (s < sizeof(ObjectHeader))
if (s < sizeof(o.object))
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read overly short object: %" PRIu64,
offset);
@ -863,6 +909,11 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O
"Attempt to read truncated object: %" PRIu64,
offset);
if ((size_t) n < minimum_header_size(&o))
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Short read while reading object: %" PRIu64,
offset);
if (type > OBJECT_UNUSED && o.object.type != type)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Attempt to read object of unexpected type: %" PRIu64,
@ -930,7 +981,7 @@ int journal_file_append_object(
if (r < 0)
return r;
r = journal_file_tail_end(f, &p);
r = journal_file_tail_end_by_mmap(f, &p);
if (r < 0)
return r;

View File

@ -185,9 +185,10 @@ static inline bool VALID_EPOCH(uint64_t u) {
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH)
int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret);
int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, Object *ret);
int journal_file_read_object_header(JournalFile *f, ObjectType type, uint64_t offset, Object *ret);
int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset);
int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset);
int journal_file_tail_end_by_mmap(JournalFile *f, uint64_t *ret_offset);
uint64_t journal_file_entry_n_items(Object *o) _pure_;
uint64_t journal_file_entry_array_n_items(Object *o) _pure_;