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:
commit
891c9b36cf
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user