From: Daan De Meyer Date: Thu, 29 Sep 2022 10:09:09 +0000 (+0200) Subject: journal: Introduce journal_file_data_payload() X-Git-Tag: v252-rc1~4^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0e35afff1db475b46281fac75fa3fc2d7f26cae7;p=thirdparty%2Fsystemd.git journal: Introduce journal_file_data_payload() journal_file_data_payload() retrieves the payload of a Data object, optionally decompressing it and checking to see if matches a given field. This function replaces all the decompression code in the sd-journal codebase with a single function. This commit should not introduce any changes in sd-journal behavior. --- diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c index 33a285faa45..67bd2305adb 100644 --- a/src/libsystemd/sd-journal/journal-file.c +++ b/src/libsystemd/sd-journal/journal-file.c @@ -1369,7 +1369,7 @@ int journal_file_find_data_object_with_hash( const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *ret_offset) { - uint64_t p, osize, h, m, depth = 0; + uint64_t p, h, m, depth = 0; int r; assert(f); @@ -1385,8 +1385,6 @@ int journal_file_find_data_object_with_hash( if (r < 0) return r; - osize = offsetof(Object, data.payload) + size; - m = le64toh(READ_NOW(f->header->data_hash_table_size)) / sizeof(HashItem); if (m <= 0) return -EBADMSG; @@ -1395,8 +1393,9 @@ int journal_file_find_data_object_with_hash( p = le64toh(f->data_hash_table[h].head_hash_offset); while (p > 0) { - Compression c; Object *o; + void *d; + size_t rsize; r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) @@ -1405,42 +1404,13 @@ int journal_file_find_data_object_with_hash( if (le64toh(o->data.hash) != hash) goto next; - c = COMPRESSION_FROM_OBJECT(o); - if (c < 0) - return -EPROTONOSUPPORT; - if (c != COMPRESSION_NONE) { -#if HAVE_COMPRESSION - uint64_t l; - size_t rsize = 0; - - l = le64toh(READ_NOW(o->object.size)); - if (l <= offsetof(Object, data.payload)) - return -EBADMSG; - - l -= offsetof(Object, data.payload); - - r = decompress_blob(c, o->data.payload, l, &f->compress_buffer, &rsize, 0); - if (r < 0) - return r; - - if (rsize == size && - memcmp(f->compress_buffer, data, size) == 0) { - - if (ret) - *ret = o; - - if (ret_offset) - *ret_offset = p; - - return 1; - } -#else - return -EPROTONOSUPPORT; -#endif - } else if (le64toh(o->object.size) == osize && - memcmp(o->data.payload, data, size) == 0) { + r = journal_file_data_payload(f, o, p, NULL, 0, 0, &d, &rsize); + if (r < 0) + return r; + assert(r > 0); /* journal_file_data_payload() always returns > 0 if no field is provided. */ - if (ret) + if (memcmp_nn(data, size, d, rsize) == 0) { + if (ret) *ret = o; if (ret_offset) @@ -1658,6 +1628,106 @@ static int journal_file_append_data( return 0; } +static int maybe_decompress_payload( + JournalFile *f, + uint8_t *payload, + uint64_t size, + Compression compression, + const char *field, + size_t field_length, + size_t data_threshold, + void **ret_data, + size_t *ret_size) { + + /* We can't read objects larger than 4G on a 32bit machine */ + if ((uint64_t) (size_t) size != size) + return -E2BIG; + + if (compression != COMPRESSION_NONE) { +#if HAVE_COMPRESSION + size_t rsize; + int r; + + if (field) { + r = decompress_startswith(compression, payload, size, &f->compress_buffer, field, + field_length, '='); + if (r < 0) + return log_debug_errno(r, + "Cannot decompress %s object of length %" PRIu64 ": %m", + compression_to_string(compression), + size); + if (r == 0) { + *ret_data = NULL; + *ret_size = 0; + return 0; + } + } + + r = decompress_blob(compression, payload, size, &f->compress_buffer, &rsize, 0); + if (r < 0) + return r; + + if (ret_data) + *ret_data = f->compress_buffer; + if (ret_size) + *ret_size = rsize; +#else + return -EPROTONOSUPPORT; +#endif + } else { + if (field && (size < field_length + 1 || memcmp(payload, field, field_length) != 0 || payload[field_length] != '=')) { + *ret_data = NULL; + *ret_size = 0; + return 0; + } + + if (ret_data) + *ret_data = payload; + if (ret_size) + *ret_size = (size_t) size; + } + + return 1; +} + +int journal_file_data_payload( + JournalFile *f, + Object *o, + uint64_t offset, + const char *field, + size_t field_length, + size_t data_threshold, + void **ret_data, + size_t *ret_size) { + + uint64_t size; + Compression c; + int r; + + assert(!field == (field_length == 0)); /* These must be specified together. */ + assert(ret_data); + assert(ret_size); + + if (!o) { + r = journal_file_move_to_object(f, OBJECT_DATA, offset, &o); + if (r < 0) + return r; + } + + size = le64toh(READ_NOW(o->object.size)); + if (size < offsetof(Object, data.payload)) + return -EBADMSG; + + size -= offsetof(Object, data.payload); + + c = COMPRESSION_FROM_OBJECT(o); + if (c < 0) + return -EPROTONOSUPPORT; + + return maybe_decompress_payload(f, o->data.payload, size, c, field, field_length, data_threshold, + ret_data, ret_size); +} + uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) { uint64_t sz; @@ -3807,51 +3877,20 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 items = newa(EntryItem, n); for (uint64_t i = 0; i < n; i++) { - Compression c; - uint64_t l, h; - size_t t; + uint64_t h; void *data; + size_t l; Object *u; q = journal_file_entry_item_object_offset(from, o, i); - - r = journal_file_move_to_object(from, OBJECT_DATA, q, &o); + r = journal_file_data_payload(from, NULL, q, NULL, 0, 0, &data, &l); + if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { + log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i); + continue; + } if (r < 0) return r; - - l = le64toh(READ_NOW(o->object.size)); - if (l < offsetof(Object, data.payload)) - return -EBADMSG; - - l -= offsetof(Object, data.payload); - t = (size_t) l; - - /* We hit the limit on 32bit machines */ - if ((uint64_t) t != l) - return -E2BIG; - - c = COMPRESSION_FROM_OBJECT(o); - if (c < 0) - return -EPROTONOSUPPORT; - if (c != COMPRESSION_NONE) { -#if HAVE_COMPRESSION - size_t rsize = 0; - - r = decompress_blob( - c, - o->data.payload, l, - &from->compress_buffer, &rsize, - 0); - if (r < 0) - return r; - - data = from->compress_buffer; - l = rsize; -#else - return -EPROTONOSUPPORT; -#endif - } else - data = o->data.payload; + assert(r > 0); if (l == 0) return -EBADMSG; @@ -3869,10 +3908,6 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 .object_offset = h, .hash = le64toh(u->data.hash), }; - - r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); - if (r < 0) - return r; } r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n, NULL, NULL, NULL); diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h index 086b4408883..79769537937 100644 --- a/src/libsystemd/sd-journal/journal-file.h +++ b/src/libsystemd/sd-journal/journal-file.h @@ -212,6 +212,17 @@ static inline size_t journal_file_entry_item_size(JournalFile *f) { } uint64_t journal_file_entry_n_items(JournalFile *f, Object *o) _pure_; + +int journal_file_data_payload( + JournalFile *f, + Object *o, + uint64_t offset, + const char *field, + size_t field_length, + size_t data_threshold, + void **ret_data, + size_t *ret_size); + uint64_t journal_file_entry_array_n_items(JournalFile *f, Object *o) _pure_; static inline uint64_t journal_file_entry_array_item(JournalFile *f, Object *o, size_t i) { diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index 8c94f02f3e8..5a75994d159 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -2289,13 +2289,14 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** uint64_t n = journal_file_entry_n_items(f, o); for (uint64_t i = 0; i < n; i++) { - Object *d; - uint64_t p, l; - size_t t; - Compression c; + uint64_t p; + void *d; + size_t l; p = journal_file_entry_item_object_offset(f, o, i); - r = journal_file_move_to_object(f, OBJECT_DATA, p, &d); + r = journal_file_data_payload(f, NULL, p, field, field_length, j->data_threshold, &d, &l); + if (r == 0) + continue; if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", i); continue; @@ -2303,117 +2304,15 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** if (r < 0) return r; - l = le64toh(d->object.size) - offsetof(Object, data.payload); - - c = COMPRESSION_FROM_OBJECT(d); - if (c < 0) - return -EPROTONOSUPPORT; - if (c != COMPRESSION_NONE) { -#if HAVE_COMPRESSION - r = decompress_startswith( - c, - d->data.payload, l, - &f->compress_buffer, - field, field_length, '='); - if (r < 0) - log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m", - compression_to_string(c), l, p); - else if (r > 0) { - - size_t rsize; - - r = decompress_blob( - c, - d->data.payload, l, - &f->compress_buffer, &rsize, - j->data_threshold); - if (r < 0) - return r; - - *data = f->compress_buffer; - *size = (size_t) rsize; - - return 0; - } -#else - return -EPROTONOSUPPORT; -#endif - } else if (l >= field_length+1 && - memcmp(d->data.payload, field, field_length) == 0 && - d->data.payload[field_length] == '=') { - - t = (size_t) l; - - if ((uint64_t) t != l) - return -E2BIG; + *data = d; + *size = l; - *data = d->data.payload; - *size = t; - - return 0; - } + return 0; } return -ENOENT; } -static int return_data( - sd_journal *j, - JournalFile *f, - Object *o, - const void **ret_data, - size_t *ret_size) { - - Compression c; - uint64_t l; - size_t t; - - assert(j); - assert(f); - - l = le64toh(READ_NOW(o->object.size)); - if (l < offsetof(Object, data.payload)) - return -EBADMSG; - l -= offsetof(Object, data.payload); - - /* We can't read objects larger than 4G on a 32bit machine */ - t = (size_t) l; - if ((uint64_t) t != l) - return -E2BIG; - - c = COMPRESSION_FROM_OBJECT(o); - if (c < 0) - return -EPROTONOSUPPORT; - if (c != COMPRESSION_NONE) { -#if HAVE_COMPRESSION - size_t rsize; - int r; - - r = decompress_blob( - c, - o->data.payload, l, - &f->compress_buffer, &rsize, - j->data_threshold); - if (r < 0) - return r; - - if (ret_data) - *ret_data = f->compress_buffer; - if (ret_size) - *ret_size = (size_t) rsize; -#else - return -EPROTONOSUPPORT; -#endif - } else { - if (ret_data) - *ret_data = o->data.payload; - if (ret_size) - *ret_size = t; - } - - return 0; -} - _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { JournalFile *f; Object *o; @@ -2437,23 +2336,21 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t for (uint64_t n = journal_file_entry_n_items(f, o); j->current_field < n; j->current_field++) { uint64_t p; + void *d; + size_t l; p = journal_file_entry_item_object_offset(f, o, j->current_field); - r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + r = journal_file_data_payload(f, NULL, p, NULL, 0, j->data_threshold, &d, &l); if (IN_SET(r, -EADDRNOTAVAIL, -EBADMSG)) { log_debug_errno(r, "Entry item %"PRIu64" data object is bad, skipping over it: %m", j->current_field); continue; } if (r < 0) return r; + assert(r > 0); - r = return_data(j, f, o, data, size); - if (r == -EBADMSG) { - log_debug("Entry item %"PRIu64" data payload is bad, skipping over it.", j->current_field); - continue; - } - if (r < 0) - return r; + *data = d; + *size = l; j->current_field++; @@ -2925,7 +2822,7 @@ _public_ int sd_journal_enumerate_unique( for (;;) { JournalFile *of; Object *o; - const void *odata; + void *odata; size_t ol; bool found; int r; @@ -2969,7 +2866,8 @@ _public_ int sd_journal_enumerate_unique( j->unique_offset, o->object.type, OBJECT_DATA); - r = return_data(j, j->unique_file, o, &odata, &ol); + r = journal_file_data_payload(j->unique_file, o, j->unique_offset, NULL, 0, + j->data_threshold, &odata, &ol); if (r < 0) return r; @@ -3016,9 +2914,8 @@ _public_ int sd_journal_enumerate_unique( if (found) continue; - r = return_data(j, j->unique_file, o, ret_data, ret_size); - if (r < 0) - return r; + *ret_data = odata; + *ret_size = ol; return 1; }