mirror of
https://github.com/systemd/systemd.git
synced 2025-08-30 05:49:54 +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:
@ -23,7 +23,7 @@ static int journald_file_truncate(JournalFile *f) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* truncate excess from the end of archives */
|
/* 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)
|
if (r < 0)
|
||||||
return log_debug_errno(r, "Failed to determine end of tail object: %m");
|
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;
|
return 0;
|
||||||
|
|
||||||
for (uint64_t q = p; q != 0; q = le64toh(o.entry_array.next_entry_array_offset)) {
|
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)
|
if (r < 0)
|
||||||
return r;
|
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;
|
for (uint64_t q = le64toh(items[j].head_hash_offset); q != 0;
|
||||||
q = le64toh(o.data.next_hash_offset)) {
|
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) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Invalid data object: %m, ignoring");
|
log_debug_errno(r, "Invalid data object: %m, ignoring");
|
||||||
break;
|
break;
|
||||||
|
@ -91,8 +91,7 @@
|
|||||||
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
# pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
|
int journal_file_tail_end_by_pread(JournalFile *f, uint64_t *ret_offset) {
|
||||||
Object tail;
|
|
||||||
uint64_t p;
|
uint64_t p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -100,13 +99,17 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
|
|||||||
assert(f->header);
|
assert(f->header);
|
||||||
assert(ret_offset);
|
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);
|
p = le64toh(f->header->tail_object_offset);
|
||||||
if (p == 0)
|
if (p == 0)
|
||||||
p = le64toh(f->header->header_size);
|
p = le64toh(f->header->header_size);
|
||||||
else {
|
else {
|
||||||
|
Object tail;
|
||||||
uint64_t sz;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -126,6 +129,43 @@ int journal_file_tail_end(JournalFile *f, uint64_t *ret_offset) {
|
|||||||
return 0;
|
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 journal_file_set_offline_thread_join(JournalFile *f) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -818,10 +858,11 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 r;
|
|
||||||
Object o;
|
|
||||||
uint64_t s;
|
uint64_t s;
|
||||||
|
ssize_t n;
|
||||||
|
Object o;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(f);
|
assert(f);
|
||||||
|
|
||||||
@ -838,17 +879,22 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O
|
|||||||
offset);
|
offset);
|
||||||
|
|
||||||
/* This will likely read too much data but it avoids having to call pread() twice. */
|
/* This will likely read too much data but it avoids having to call pread() twice. */
|
||||||
r = pread(f->fd, &o, sizeof(Object), offset);
|
n = pread(f->fd, &o, sizeof(o), offset);
|
||||||
if (r < 0)
|
if (n < 0)
|
||||||
return r;
|
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);
|
s = le64toh(o.object.size);
|
||||||
|
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||||
"Attempt to read uninitialized object: %" PRIu64,
|
"Attempt to read uninitialized object: %" PRIu64,
|
||||||
offset);
|
offset);
|
||||||
if (s < sizeof(ObjectHeader))
|
if (s < sizeof(o.object))
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||||
"Attempt to read overly short object: %" PRIu64,
|
"Attempt to read overly short object: %" PRIu64,
|
||||||
offset);
|
offset);
|
||||||
@ -863,6 +909,11 @@ int journal_file_read_object(JournalFile *f, ObjectType type, uint64_t offset, O
|
|||||||
"Attempt to read truncated object: %" PRIu64,
|
"Attempt to read truncated object: %" PRIu64,
|
||||||
offset);
|
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)
|
if (type > OBJECT_UNUSED && o.object.type != type)
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||||
"Attempt to read object of unexpected type: %" PRIu64,
|
"Attempt to read object of unexpected type: %" PRIu64,
|
||||||
@ -930,7 +981,7 @@ int journal_file_append_object(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = journal_file_tail_end(f, &p);
|
r = journal_file_tail_end_by_mmap(f, &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -185,9 +185,10 @@ static inline bool VALID_EPOCH(uint64_t u) {
|
|||||||
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_KEYED_HASH)
|
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_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_n_items(Object *o) _pure_;
|
||||||
uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
|
uint64_t journal_file_entry_array_n_items(Object *o) _pure_;
|
||||||
|
Reference in New Issue
Block a user