Skip to content

Commit f14f127

Browse files
authored
Merge pull request #27526 from mrc0mmand/journal-fss
journal: clean up the FSS related code a bit & add a couple of tests
2 parents ef43006 + 6ce3d33 commit f14f127

File tree

2 files changed

+111
-91
lines changed

2 files changed

+111
-91
lines changed

src/libsystemd/sd-journal/journal-authenticate.c

Lines changed: 65 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@
1313
#include "memory-util.h"
1414
#include "time-util.h"
1515

16+
static void* fssheader_free(FSSHeader *p) {
17+
/* mmap() returns MAP_FAILED on error and sets the errno */
18+
if (!p || p == MAP_FAILED)
19+
return NULL;
20+
21+
assert_se(munmap(p, PAGE_ALIGN(sizeof(FSSHeader))) >= 0);
22+
return NULL;
23+
}
24+
25+
DEFINE_TRIVIAL_CLEANUP_FUNC(FSSHeader*, fssheader_free);
26+
1627
static uint64_t journal_file_tag_seqnum(JournalFile *f) {
1728
uint64_t r;
1829

@@ -96,8 +107,7 @@ static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *e
96107
assert(epoch);
97108
assert(JOURNAL_HEADER_SEALED(f->header));
98109

99-
if (f->fss_start_usec == 0 ||
100-
f->fss_interval_usec == 0)
110+
if (f->fss_start_usec == 0 || f->fss_interval_usec == 0)
101111
return -EOPNOTSUPP;
102112

103113
if (realtime < f->fss_start_usec)
@@ -107,12 +117,14 @@ static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *e
107117
t = t / f->fss_interval_usec;
108118

109119
*epoch = t;
120+
110121
return 0;
111122
}
112123

113124
static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) {
114125
uint64_t goal, epoch;
115126
int r;
127+
116128
assert(f);
117129

118130
if (!JOURNAL_HEADER_SEALED(f->header))
@@ -175,7 +187,7 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
175187
if (goal == epoch)
176188
return 0;
177189

178-
if (goal == epoch+1) {
190+
if (goal == epoch + 1) {
179191
FSPRG_Evolve(f->fsprg_state);
180192
return 0;
181193
}
@@ -191,6 +203,7 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
191203
msk = alloca_safe(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
192204
FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
193205
FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
206+
194207
return 0;
195208
}
196209

@@ -236,10 +249,8 @@ int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uin
236249
r = journal_file_move_to_object(f, type, p, &o);
237250
if (r < 0)
238251
return r;
239-
} else {
240-
if (type > OBJECT_UNUSED && o->object.type != type)
241-
return -EBADMSG;
242-
}
252+
} else if (type > OBJECT_UNUSED && o->object.type != type)
253+
return -EBADMSG;
243254

244255
gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
245256

@@ -308,11 +319,12 @@ int journal_file_hmac_put_header(JournalFile *f) {
308319
}
309320

310321
int journal_file_fss_load(JournalFile *f) {
311-
int r, fd = -EBADF;
312-
char *p = NULL;
322+
_cleanup_close_ int fd = -EBADF;
323+
_cleanup_free_ char *path = NULL;
324+
_cleanup_(fssheader_freep) FSSHeader *header = NULL;
313325
struct stat st;
314-
FSSHeader *m = NULL;
315326
sd_id128_t machine;
327+
int r;
316328

317329
assert(f);
318330

@@ -323,78 +335,54 @@ int journal_file_fss_load(JournalFile *f) {
323335
if (r < 0)
324336
return r;
325337

326-
if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
338+
if (asprintf(&path, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
327339
SD_ID128_FORMAT_VAL(machine)) < 0)
328340
return -ENOMEM;
329341

330-
fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
342+
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
331343
if (fd < 0) {
332344
if (errno != ENOENT)
333-
log_error_errno(errno, "Failed to open %s: %m", p);
345+
log_error_errno(errno, "Failed to open %s: %m", path);
334346

335-
r = -errno;
336-
goto finish;
347+
return -errno;
337348
}
338349

339-
if (fstat(fd, &st) < 0) {
340-
r = -errno;
341-
goto finish;
342-
}
350+
if (fstat(fd, &st) < 0)
351+
return -errno;
343352

344-
if (st.st_size < (off_t) sizeof(FSSHeader)) {
345-
r = -ENODATA;
346-
goto finish;
347-
}
353+
if (st.st_size < (off_t) sizeof(FSSHeader))
354+
return -ENODATA;
348355

349-
m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
350-
if (m == MAP_FAILED) {
351-
m = NULL;
352-
r = -errno;
353-
goto finish;
354-
}
356+
header = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
357+
if (header == MAP_FAILED)
358+
return -errno;
355359

356-
if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) {
357-
r = -EBADMSG;
358-
goto finish;
359-
}
360+
if (memcmp(header->signature, FSS_HEADER_SIGNATURE, 8) != 0)
361+
return -EBADMSG;
360362

361-
if (m->incompatible_flags != 0) {
362-
r = -EPROTONOSUPPORT;
363-
goto finish;
364-
}
363+
if (header->incompatible_flags != 0)
364+
return -EPROTONOSUPPORT;
365365

366-
if (le64toh(m->header_size) < sizeof(FSSHeader)) {
367-
r = -EBADMSG;
368-
goto finish;
369-
}
366+
if (le64toh(header->header_size) < sizeof(FSSHeader))
367+
return -EBADMSG;
370368

371-
if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) {
372-
r = -EBADMSG;
373-
goto finish;
374-
}
369+
if (le64toh(header->fsprg_state_size) != FSPRG_stateinbytes(le16toh(header->fsprg_secpar)))
370+
return -EBADMSG;
375371

376-
f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size);
377-
if ((uint64_t) st.st_size < f->fss_file_size) {
378-
r = -ENODATA;
379-
goto finish;
380-
}
372+
f->fss_file_size = le64toh(header->header_size) + le64toh(header->fsprg_state_size);
373+
if ((uint64_t) st.st_size < f->fss_file_size)
374+
return -ENODATA;
381375

382-
if (!sd_id128_equal(machine, m->machine_id)) {
383-
r = -EHOSTDOWN;
384-
goto finish;
385-
}
376+
if (!sd_id128_equal(machine, header->machine_id))
377+
return -EHOSTDOWN;
386378

387-
if (le64toh(m->start_usec) <= 0 ||
388-
le64toh(m->interval_usec) <= 0) {
389-
r = -EBADMSG;
390-
goto finish;
391-
}
379+
if (le64toh(header->start_usec) <= 0 || le64toh(header->interval_usec) <= 0)
380+
return -EBADMSG;
392381

393382
f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
394383
if (f->fss_file == MAP_FAILED) {
395384
f->fss_file = NULL;
396-
r = -errno;
397-
goto finish;
385+
return -errno;
398386
}
399387

400388
f->fss_start_usec = le64toh(f->fss_file->start_usec);
@@ -403,16 +391,7 @@ int journal_file_fss_load(JournalFile *f) {
403391
f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size);
404392
f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size);
405393

406-
r = 0;
407-
408-
finish:
409-
if (m)
410-
munmap(m, PAGE_ALIGN(sizeof(FSSHeader)));
411-
412-
safe_close(fd);
413-
free(p);
414-
415-
return r;
394+
return 0;
416395
}
417396

418397
int journal_file_hmac_setup(JournalFile *f) {
@@ -431,8 +410,8 @@ int journal_file_hmac_setup(JournalFile *f) {
431410
}
432411

433412
int journal_file_append_first_tag(JournalFile *f) {
434-
int r;
435413
uint64_t p;
414+
int r;
436415

437416
if (!JOURNAL_HEADER_SEALED(f->header))
438417
return 0;
@@ -469,53 +448,48 @@ int journal_file_append_first_tag(JournalFile *f) {
469448
}
470449

471450
int journal_file_parse_verification_key(JournalFile *f, const char *key) {
472-
uint8_t *seed;
473-
size_t seed_size, c;
451+
_cleanup_free_ uint8_t *seed = NULL;
452+
size_t seed_size;
474453
const char *k;
475-
int r;
476454
unsigned long long start, interval;
455+
int r;
456+
457+
assert(f);
458+
assert(key);
477459

478460
seed_size = FSPRG_RECOMMENDED_SEEDLEN;
479461
seed = malloc(seed_size);
480462
if (!seed)
481463
return -ENOMEM;
482464

483465
k = key;
484-
for (c = 0; c < seed_size; c++) {
466+
for (size_t c = 0; c < seed_size; c++) {
485467
int x, y;
486468

487-
while (*k == '-')
488-
k++;
469+
k = skip_leading_chars(k, "-");
489470

490471
x = unhexchar(*k);
491-
if (x < 0) {
492-
free(seed);
472+
if (x < 0)
493473
return -EINVAL;
494-
}
495474
k++;
475+
496476
y = unhexchar(*k);
497-
if (y < 0) {
498-
free(seed);
477+
if (y < 0)
499478
return -EINVAL;
500-
}
501479
k++;
502480

503481
seed[c] = (uint8_t) (x * 16 + y);
504482
}
505483

506-
if (*k != '/') {
507-
free(seed);
484+
if (*k != '/')
508485
return -EINVAL;
509-
}
510486
k++;
511487

512488
r = sscanf(k, "%llx-%llx", &start, &interval);
513-
if (r != 2) {
514-
free(seed);
489+
if (r != 2)
515490
return -EINVAL;
516-
}
517491

518-
f->fsprg_seed = seed;
492+
f->fsprg_seed = TAKE_PTR(seed);
519493
f->fsprg_seed_size = seed_size;
520494

521495
f->fss_start_usec = start * interval;

test/units/testsuite-04.fss.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: LGPL-2.1-or-later
3+
set -eux
4+
set -o pipefail
5+
6+
# Forward Secure Sealing
7+
8+
if ! journalctl --version | grep -qF +GCRYPT; then
9+
echo "Built without gcrypt, skipping the FSS tests"
10+
exit 0
11+
fi
12+
13+
journalctl --force --setup-keys --interval=2 |& tee /tmp/fss
14+
FSS_VKEY="$(sed -rn '/([a-f0-9]{6}\-){3}[a-f0-9]{6}\/[a-f0-9]+\-[a-f0-9]+/p' /tmp/fss)"
15+
[[ -n "$FSS_VKEY" ]]
16+
17+
# Generate some buzz in the journal and wait until the FSS key is changed
18+
# at least once
19+
systemd-cat cat /etc/os-release
20+
sleep 4
21+
# Seal the journal
22+
journalctl --rotate
23+
# Verification should fail without a valid FSS key
24+
(! journalctl --verify)
25+
(! journalctl --verify --verify-key="")
26+
(! journalctl --verify --verify-key="000000-000000-000000-000000/00000000-00000")
27+
# FIXME: ignore --verify result until #27532 is resolved
28+
journalctl --verify --verify-key="$FSS_VKEY" || :
29+
30+
# Sealing + systemd-journal-remote
31+
/usr/lib/systemd/systemd-journal-remote --getter="journalctl -n 5 -o export" \
32+
--split-mode=none \
33+
--seal=yes \
34+
--output=/tmp/sealed.journal
35+
(! journalctl --file=/tmp/sealed.journal --verify)
36+
(! journalctl --file=/tmp/sealed.journal --verify --verify-key="")
37+
(! journalctl --file=/tmp/sealed.journal --verify --verify-key="000000-000000-000000-000000/00000000-00000")
38+
# FIXME: ignore --verify result until #27532 is resolved
39+
journalctl --file=/tmp/sealed.journal --verify --verify-key="$FSS_VKEY" || :
40+
rm -f /tmp/sealed.journal
41+
42+
# Return back to a journal without FSS
43+
rm -fv "/var/log/journal/$(</etc/machine-id)/fss"
44+
journalctl --rotate --vacuum-size=1
45+
# FIXME: ignore --verify result until #27532 is resolved
46+
journalctl --verify || :

0 commit comments

Comments
 (0)