summaryrefslogtreecommitdiffstats
path: root/src/libsystemd
diff options
context:
space:
mode:
authorfelixdoerre <felixdoerre@users.noreply.github.com>2023-10-06 05:18:21 +0200
committerGitHub <noreply@github.com>2023-10-06 05:18:21 +0200
commit3846d3aa292a6daa1916f667bdd79ebee9cb4ac4 (patch)
tree4ef7a07ed5ff05e2f53a46956d9856190fd2045e /src/libsystemd
parentbacklight: support to specify percentage of minimum brightness (diff)
downloadsystemd-3846d3aa292a6daa1916f667bdd79ebee9cb4ac4.tar.xz
systemd-3846d3aa292a6daa1916f667bdd79ebee9cb4ac4.zip
journalctl: verify that old entries are not sealed with too recent key (#28885)
When verifying seals produced with forward secure sealing, the verification currently does not check that old entries are only sealed with the key for their epoch and not a more recent one. This missing check allows an attacker to remove seals, and create new ones with the currently available key, and verify will claim everything is in order, although all entries could have been modified. This resolves CVE-2023-31439. Co-authored-by: Felix Dörre <felix.doerre@kit.edu>
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-journal/journal-verify.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/libsystemd/sd-journal/journal-verify.c b/src/libsystemd/sd-journal/journal-verify.c
index cdfe7a1a6a..aa086c651e 100644
--- a/src/libsystemd/sd-journal/journal-verify.c
+++ b/src/libsystemd/sd-journal/journal-verify.c
@@ -819,6 +819,7 @@ int journal_file_verify(
uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
+ usec_t min_entry_realtime = USEC_INFINITY, max_entry_realtime = 0;
sd_id128_t entry_boot_id = {}; /* Unnecessary initialization to appease gcc */
bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
uint64_t n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
@@ -1070,6 +1071,9 @@ int journal_file_verify(
entry_realtime = le64toh(o->entry.realtime);
entry_realtime_set = true;
+ max_entry_realtime = MAX(max_entry_realtime, le64toh(o->entry.realtime));
+ min_entry_realtime = MIN(min_entry_realtime, le64toh(o->entry.realtime));
+
n_entries++;
break;
@@ -1135,12 +1139,13 @@ int journal_file_verify(
#if HAVE_GCRYPT
if (JOURNAL_HEADER_SEALED(f->header)) {
- uint64_t q, rt;
+ uint64_t q, rt, rt_end;
debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));
rt = f->fss_start_usec + le64toh(o->tag.epoch) * f->fss_interval_usec;
- if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
+ rt_end = usec_add(rt, f->fss_interval_usec);
+ if (entry_realtime_set && entry_realtime >= rt_end) {
error(p,
"tag/entry realtime timestamp out of synchronization (%"PRIu64" >= %"PRIu64")",
entry_realtime,
@@ -1148,6 +1153,23 @@ int journal_file_verify(
r = -EBADMSG;
goto fail;
}
+ if (max_entry_realtime >= rt_end) {
+ error(p,
+ "Entry realtime (%"PRIu64", %s) is too late with respect to tag (%"PRIu64", %s)",
+ max_entry_realtime, FORMAT_TIMESTAMP(max_entry_realtime),
+ rt_end, FORMAT_TIMESTAMP(rt_end));
+ r = -EBADMSG;
+ goto fail;
+ }
+ if (min_entry_realtime < rt) {
+ error(p,
+ "Entry realtime (%"PRIu64", %s) is too early with respect to tag (%"PRIu64", %s)",
+ min_entry_realtime, FORMAT_TIMESTAMP(min_entry_realtime),
+ rt, FORMAT_TIMESTAMP(rt));
+ r = -EBADMSG;
+ goto fail;
+ }
+ min_entry_realtime = USEC_INFINITY;
/* OK, now we know the epoch. So let's now set
* it, and calculate the HMAC for everything