summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-01-26 16:49:36 +0100
committerLennart Poettering <lennart@poettering.net>2023-02-21 10:47:53 +0100
commit9204fc642acef5cfc3a411fdec3ce9a5fd9f8d37 (patch)
tree714e364dc766868d2391532cc88cb9ad2ed222c9
parent512f2da5c7009bbc72ce2167badd50c06aa0037a (diff)
downloadsystemd-9204fc642acef5cfc3a411fdec3ce9a5fd9f8d37.tar.gz
journal-file: don't update boot_id in journal header on open
The header of the journal file contains a boot ID field that is currently updated whenever we open the journal file. This is not ideal: pretty often we want to archive a journal file, and need to open it for that. Archiving a foreign journal file should not mark it as ours, it should just change the status flag in the file header. The boot ID in the header is aleady rewritten whenever we write a journal entry to the file anyway, hence all this patch effectively does is slightly "delay" when the boot ID in the header is updated: instead of immediately on open it is updated on the first entry that is written. Net effect: archived journal files don't all look like they were written to on a boot newer then they actually were And more importantly: the "tail_entry_monotonic" field suddenly becomes useful, since we know which boot it belongs to. Generally, monotonic timestamps without boot ID information are useless, and this fixes it. A new (compatible) header flag marks file where the boot_id can be understood this way. This can be used by code that wants to make use of the "tail_entry_monotonic" field to ensure it actually can do so safely. This also renames the structure definition in journal-def accordingly, to indicate we now follow the stricter semantics for it.
-rw-r--r--src/journal/test-journal-interleaving.c4
-rw-r--r--src/libsystemd/sd-journal/journal-authenticate.c2
-rw-r--r--src/libsystemd/sd-journal/journal-def.h41
-rw-r--r--src/libsystemd/sd-journal/journal-file.c22
-rw-r--r--src/libsystemd/sd-journal/journal-file.h3
-rw-r--r--src/libsystemd/sd-journal/journal-verify.c3
6 files changed, 40 insertions, 35 deletions
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index 55d717da31..7fec6d9eea 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -230,7 +230,7 @@ static void test_sequence_numbers_one(void) {
assert_se(one->file->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->machine_id));
- assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->boot_id));
+ assert_se(!sd_id128_equal(one->file->header->file_id, one->file->header->tail_entry_boot_id));
assert_se(sd_id128_equal(one->file->header->file_id, one->file->header->seqnum_id));
memcpy(&seqnum_id, &one->file->header->seqnum_id, sizeof(sd_id128_t));
@@ -241,7 +241,7 @@ static void test_sequence_numbers_one(void) {
assert_se(two->file->header->state == STATE_ONLINE);
assert_se(!sd_id128_equal(two->file->header->file_id, one->file->header->file_id));
assert_se(sd_id128_equal(one->file->header->machine_id, one->file->header->machine_id));
- assert_se(sd_id128_equal(one->file->header->boot_id, one->file->header->boot_id));
+ assert_se(sd_id128_equal(one->file->header->tail_entry_boot_id, one->file->header->tail_entry_boot_id));
assert_se(sd_id128_equal(one->file->header->seqnum_id, one->file->header->seqnum_id));
append_number(two, 3, &seqnum);
diff --git a/src/libsystemd/sd-journal/journal-authenticate.c b/src/libsystemd/sd-journal/journal-authenticate.c
index 3c5d9d7e49..159e215367 100644
--- a/src/libsystemd/sd-journal/journal-authenticate.c
+++ b/src/libsystemd/sd-journal/journal-authenticate.c
@@ -300,7 +300,7 @@ int journal_file_hmac_put_header(JournalFile *f) {
* n_entry_arrays. */
gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
- gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
+ gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, tail_entry_boot_id) - offsetof(Header, file_id));
gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
diff --git a/src/libsystemd/sd-journal/journal-def.h b/src/libsystemd/sd-journal/journal-def.h
index d35290d3c7..fb22fc45f3 100644
--- a/src/libsystemd/sd-journal/journal-def.h
+++ b/src/libsystemd/sd-journal/journal-def.h
@@ -173,32 +173,31 @@ enum {
HEADER_INCOMPATIBLE_KEYED_HASH = 1 << 2,
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD = 1 << 3,
HEADER_INCOMPATIBLE_COMPACT = 1 << 4,
-};
-#define HEADER_INCOMPATIBLE_ANY \
- (HEADER_INCOMPATIBLE_COMPRESSED_XZ | \
- HEADER_INCOMPATIBLE_COMPRESSED_LZ4 | \
- HEADER_INCOMPATIBLE_KEYED_HASH | \
- HEADER_INCOMPATIBLE_COMPRESSED_ZSTD | \
- HEADER_INCOMPATIBLE_COMPACT)
+ HEADER_INCOMPATIBLE_ANY = HEADER_INCOMPATIBLE_COMPRESSED_XZ |
+ HEADER_INCOMPATIBLE_COMPRESSED_LZ4 |
+ HEADER_INCOMPATIBLE_KEYED_HASH |
+ HEADER_INCOMPATIBLE_COMPRESSED_ZSTD |
+ HEADER_INCOMPATIBLE_COMPACT,
+
+ HEADER_INCOMPATIBLE_SUPPORTED = (HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) |
+ (HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) |
+ (HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) |
+ HEADER_INCOMPATIBLE_KEYED_HASH |
+ HEADER_INCOMPATIBLE_COMPACT,
+};
-#define HEADER_INCOMPATIBLE_SUPPORTED \
- ((HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) | \
- (HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) | \
- (HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) | \
- HEADER_INCOMPATIBLE_KEYED_HASH | \
- HEADER_INCOMPATIBLE_COMPACT)
enum {
- HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_SEALED = 1 << 0,
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID = 1 << 1, /* if set, the last_entry_boot_id field in the header is exclusively refreshed when an entry is appended */
+ HEADER_COMPATIBLE_ANY = HEADER_COMPATIBLE_SEALED|
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
+
+ HEADER_COMPATIBLE_SUPPORTED = (HAVE_GCRYPT ? HEADER_COMPATIBLE_SEALED : 0) |
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID,
};
-#define HEADER_COMPATIBLE_ANY HEADER_COMPATIBLE_SEALED
-#if HAVE_GCRYPT
-# define HEADER_COMPATIBLE_SUPPORTED HEADER_COMPATIBLE_SEALED
-#else
-# define HEADER_COMPATIBLE_SUPPORTED 0
-#endif
#define HEADER_SIGNATURE \
((const uint8_t[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
@@ -211,7 +210,7 @@ enum {
uint8_t reserved[7]; \
sd_id128_t file_id; \
sd_id128_t machine_id; \
- sd_id128_t boot_id; /* last writer */ \
+ sd_id128_t tail_entry_boot_id; \
sd_id128_t seqnum_id; \
le64_t header_size; \
le64_t arena_size; \
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index aab33dbfcc..d361b35a6e 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -357,7 +357,9 @@ static int journal_file_init_header(
FLAGS_SET(file_flags, JOURNAL_COMPRESS) * COMPRESSION_TO_HEADER_INCOMPATIBLE_FLAG(DEFAULT_COMPRESSION) |
keyed_hash_requested() * HEADER_INCOMPATIBLE_KEYED_HASH |
compact_mode_requested() * HEADER_INCOMPATIBLE_COMPACT),
- .compatible_flags = htole32(seal * HEADER_COMPATIBLE_SEALED),
+ .compatible_flags = htole32(
+ (seal * HEADER_COMPATIBLE_SEALED) |
+ HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID),
};
assert_cc(sizeof(h.signature) == sizeof(HEADER_SIGNATURE));
@@ -397,9 +399,8 @@ static int journal_file_refresh_header(JournalFile *f) {
f->header->machine_id = SD_ID128_NULL;
}
- r = sd_id128_get_boot(&f->header->boot_id);
- if (r < 0)
- return r;
+ /* We used to update the header's boot ID field here, but we don't do that anymore, as per
+ * HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID */
r = journal_file_set_online(f);
@@ -2126,9 +2127,9 @@ static int journal_file_append_entry_internal(
"timestamp %" PRIu64 ", refusing entry.",
ts->realtime, le64toh(f->header->tail_entry_realtime));
- if (!sd_id128_is_null(f->header->boot_id) && boot_id) {
+ if (!sd_id128_is_null(f->header->tail_entry_boot_id) && boot_id) {
- if (!sd_id128_equal(f->header->boot_id, *boot_id))
+ if (!sd_id128_equal(f->header->tail_entry_boot_id, *boot_id))
return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE),
"Boot ID to write is different from previous boot id, refusing entry.");
@@ -2166,8 +2167,8 @@ static int journal_file_append_entry_internal(
o->entry.monotonic = htole64(ts->monotonic);
o->entry.xor_hash = htole64(xor_hash);
if (boot_id)
- f->header->boot_id = *boot_id;
- o->entry.boot_id = f->header->boot_id;
+ f->header->tail_entry_boot_id = *boot_id;
+ o->entry.boot_id = f->header->tail_entry_boot_id;
for (size_t i = 0; i < n_items; i++)
write_entry_item(f, o, i, &items[i]);
@@ -3567,7 +3568,7 @@ void journal_file_print_header(JournalFile *f) {
"Boot ID: %s\n"
"Sequential number ID: %s\n"
"State: %s\n"
- "Compatible flags:%s%s\n"
+ "Compatible flags:%s%s%s\n"
"Incompatible flags:%s%s%s%s%s%s\n"
"Header size: %"PRIu64"\n"
"Arena size: %"PRIu64"\n"
@@ -3584,12 +3585,13 @@ void journal_file_print_header(JournalFile *f) {
f->path,
SD_ID128_TO_STRING(f->header->file_id),
SD_ID128_TO_STRING(f->header->machine_id),
- SD_ID128_TO_STRING(f->header->boot_id),
+ SD_ID128_TO_STRING(f->header->tail_entry_boot_id),
SD_ID128_TO_STRING(f->header->seqnum_id),
f->header->state == STATE_OFFLINE ? "OFFLINE" :
f->header->state == STATE_ONLINE ? "ONLINE" :
f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN",
JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "",
+ JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) ? " TAIL_ENTRY_BOOT_ID" : "",
(le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANY) ? " ???" : "",
JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" : "",
JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4" : "",
diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h
index 07f1f5d180..c1f1ab4e4f 100644
--- a/src/libsystemd/sd-journal/journal-file.h
+++ b/src/libsystemd/sd-journal/journal-file.h
@@ -180,6 +180,9 @@ static inline bool VALID_EPOCH(uint64_t u) {
#define JOURNAL_HEADER_SEALED(h) \
FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_SEALED)
+#define JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(h) \
+ FLAGS_SET(le32toh((h)->compatible_flags), HEADER_COMPATIBLE_TAIL_ENTRY_BOOT_ID)
+
#define JOURNAL_HEADER_COMPRESSED_XZ(h) \
FLAGS_SET(le32toh((h)->incompatible_flags), HEADER_INCOMPATIBLE_COMPRESSED_XZ)
diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c
index b4ce3881a4..8232f53eb6 100644
--- a/src/libsystemd/sd-journal/journal-verify.c
+++ b/src/libsystemd/sd-journal/journal-verify.c
@@ -1297,7 +1297,8 @@ int journal_file_verify(
}
if (entry_monotonic_set &&
- (sd_id128_equal(entry_boot_id, f->header->boot_id) &&
+ (sd_id128_equal(entry_boot_id, f->header->tail_entry_boot_id) &&
+ JOURNAL_HEADER_TAIL_ENTRY_BOOT_ID(f->header) &&
entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
error(0,
"Invalid tail monotonic timestamp (%"PRIu64" != %"PRIu64")",