diff options
author | Luca Boccassi <bluca@debian.org> | 2023-04-25 01:08:46 +0100 |
---|---|---|
committer | Luca Boccassi <bluca@debian.org> | 2023-04-25 12:24:25 +0100 |
commit | e046719b749ebba5d44d92c7e0a9fb207d545ff7 (patch) | |
tree | 0d39531a5d3302aaa6fd358fdbb6eaed116d06ab /src | |
parent | bf876e3f3e7c38635547cd87de7621eb8e3e946c (diff) | |
download | systemd-e046719b749ebba5d44d92c7e0a9fb207d545ff7.tar.gz |
sd-journal: store and compare per-module static origin id
sd-journal objects use hashmaps, which use module-global state, so it is not safe
to pass a sd-journal object created by a module instance to another module instance
(e.g.: when two libraries static linking sd-journal are pulled in a single process).
Initialize a random per-module origin id and store it in the object, and compare
it when entering a public API, and error out if they don't match, together with
the PID.
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd/sd-journal/journal-internal.h | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/sd-journal.c | 88 | ||||
-rw-r--r-- | src/libsystemd/sd-journal/test-journal-init.c | 19 |
3 files changed, 61 insertions, 48 deletions
diff --git a/src/libsystemd/sd-journal/journal-internal.h b/src/libsystemd/sd-journal/journal-internal.h index 60e448dac0..259aac847d 100644 --- a/src/libsystemd/sd-journal/journal-internal.h +++ b/src/libsystemd/sd-journal/journal-internal.h @@ -87,7 +87,7 @@ struct sd_journal { Match *level0, *level1, *level2; - pid_t original_pid; + uint64_t origin_id; int inotify_fd; unsigned current_invalidate_counter, last_invalidate_counter; diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index 8964140f7a..b0194e875c 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -33,6 +33,7 @@ #include "list.h" #include "lookup3.h" #include "nulstr-util.h" +#include "origin-id.h" #include "path-util.h" #include "prioq.h" #include "process-util.h" @@ -51,19 +52,12 @@ #define DEFAULT_DATA_THRESHOLD (64*1024) +DEFINE_PRIVATE_ORIGIN_ID_HELPERS(sd_journal, journal); + static void remove_file_real(sd_journal *j, JournalFile *f); static int journal_file_read_tail_timestamp(sd_journal *j, JournalFile *f); static void journal_file_unlink_newest_by_bood_id(sd_journal *j, JournalFile *f); -static bool journal_pid_changed(sd_journal *j) { - assert(j); - - /* We don't support people creating a journal object and - * keeping it around over a fork(). Let's complain. */ - - return j->original_pid != getpid_cached(); -} - static int journal_put_error(sd_journal *j, int r, const char *path) { _cleanup_free_ char *copy = NULL; int k; @@ -234,7 +228,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) uint64_t hash; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(data, -EINVAL); if (size == 0) @@ -330,7 +324,7 @@ fail: _public_ int sd_journal_add_conjunction(sd_journal *j) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); if (!j->level0) return 0; @@ -349,7 +343,7 @@ _public_ int sd_journal_add_conjunction(sd_journal *j) { _public_ int sd_journal_add_disjunction(sd_journal *j) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); if (!j->level0) return 0; @@ -406,7 +400,7 @@ char *journal_make_match_string(sd_journal *j) { } _public_ void sd_journal_flush_matches(sd_journal *j) { - if (!j) + if (!j || journal_origin_changed(j)) return; if (j->level0) @@ -930,7 +924,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); r = iterated_cache_get(j->files_cache, NULL, &files, &n_files); if (r < 0) @@ -988,7 +982,7 @@ static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t int c = 0, r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(skip <= INT_MAX, -ERANGE); if (skip == 0) { @@ -1031,7 +1025,7 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(cursor, -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) @@ -1064,7 +1058,7 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(!isempty(cursor), -EINVAL); for (const char *p = cursor;;) { @@ -1160,7 +1154,7 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { Object *o; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(!isempty(cursor), -EINVAL); if (!j->current_file || j->current_file->current_offset <= 0) @@ -1239,7 +1233,7 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); detach_location(j); @@ -1255,7 +1249,7 @@ _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, u _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); detach_location(j); @@ -1270,7 +1264,7 @@ _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { _public_ int sd_journal_seek_head(sd_journal *j) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); detach_location(j); @@ -1283,7 +1277,7 @@ _public_ int sd_journal_seek_head(sd_journal *j) { _public_ int sd_journal_seek_tail(sd_journal *j) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); detach_location(j); @@ -2001,7 +1995,7 @@ static sd_journal *journal_new(int flags, const char *path, const char *namespac return NULL; *j = (sd_journal) { - .original_pid = getpid_cached(), + .origin_id = origin_id_query(), .toplevel_fd = -EBADF, .inotify_fd = -EBADF, .flags = flags, @@ -2254,7 +2248,7 @@ _public_ void sd_journal_close(sd_journal *j) { Directory *d; Prioq *p; - if (!j) + if (!j || journal_origin_changed(j)) return; while ((p = hashmap_first(j->newest_by_boot_id))) @@ -2470,7 +2464,7 @@ _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); f = j->current_file; if (!f) @@ -2498,7 +2492,7 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); f = j->current_file; if (!f) @@ -2543,7 +2537,7 @@ _public_ int sd_journal_get_seqnum( int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); f = j->current_file; if (!f) @@ -2597,7 +2591,7 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(field, -EINVAL); assert_return(data, -EINVAL); assert_return(size, -EINVAL); @@ -2654,7 +2648,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(data, -EINVAL); assert_return(size, -EINVAL); @@ -2715,7 +2709,7 @@ _public_ int sd_journal_enumerate_available_data(sd_journal *j, const void **dat } _public_ void sd_journal_restart_data(sd_journal *j) { - if (!j) + if (!j || journal_origin_changed(j)) return; j->current_field = 0; @@ -2743,7 +2737,7 @@ _public_ int sd_journal_get_fd(sd_journal *j) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); if (j->no_inotify) return -EMEDIUMTYPE; @@ -2769,7 +2763,7 @@ _public_ int sd_journal_get_events(sd_journal *j) { int fd; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); fd = sd_journal_get_fd(j); if (fd < 0) @@ -2782,7 +2776,7 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) { int fd; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(timeout_usec, -EINVAL); fd = sd_journal_get_fd(j); @@ -2905,7 +2899,7 @@ _public_ int sd_journal_process(sd_journal *j) { bool got_something = false; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */ return 0; @@ -2937,7 +2931,7 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { uint64_t t; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); if (j->inotify_fd < 0) { JournalFile *f; @@ -2990,7 +2984,7 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(from || to, -EINVAL); assert_return(from != to, -EINVAL); @@ -3035,7 +3029,7 @@ _public_ int sd_journal_get_cutoff_monotonic_usec( int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(ret_from != ret_to, -EINVAL); ORDERED_HASHMAP_FOREACH(f, j->files) { @@ -3088,7 +3082,7 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *ret) { uint64_t sum = 0; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(ret, -EINVAL); ORDERED_HASHMAP_FOREACH(f, j->files) { @@ -3116,7 +3110,7 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(!isempty(field), -EINVAL); assert_return(field_is_valid(field), -EINVAL); @@ -3139,7 +3133,7 @@ _public_ int sd_journal_enumerate_unique( size_t k; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(j->unique_field, -EINVAL); k = strlen(j->unique_field); @@ -3272,7 +3266,7 @@ _public_ int sd_journal_enumerate_available_unique(sd_journal *j, const void **d } _public_ void sd_journal_restart_unique(sd_journal *j) { - if (!j) + if (!j || journal_origin_changed(j)) return; j->unique_file = NULL; @@ -3284,7 +3278,7 @@ _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(field, -EINVAL); if (!j->fields_file) { @@ -3423,7 +3417,7 @@ _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { } _public_ void sd_journal_restart_fields(sd_journal *j) { - if (!j) + if (!j || journal_origin_changed(j)) return; j->fields_file = NULL; @@ -3434,7 +3428,7 @@ _public_ void sd_journal_restart_fields(sd_journal *j) { _public_ int sd_journal_reliable_fd(sd_journal *j) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); return !j->on_network; } @@ -3466,7 +3460,7 @@ _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) { int r; assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(ret, -EINVAL); r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size); @@ -3501,7 +3495,7 @@ _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) { _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); j->data_threshold = sz; return 0; @@ -3509,7 +3503,7 @@ _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) { assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!journal_origin_changed(j), -ECHILD); assert_return(sz, -EINVAL); *sz = j->data_threshold; diff --git a/src/libsystemd/sd-journal/test-journal-init.c b/src/libsystemd/sd-journal/test-journal-init.c index d5702db330..c8a19779f5 100644 --- a/src/libsystemd/sd-journal/test-journal-init.c +++ b/src/libsystemd/sd-journal/test-journal-init.c @@ -1,10 +1,14 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include <unistd.h> + #include "sd-journal.h" #include "chattr-util.h" +#include "journal-internal.h" #include "log.h" #include "parse-util.h" +#include "process-util.h" #include "rm-rf.h" #include "tests.h" @@ -35,6 +39,21 @@ int main(int argc, char *argv[]) { r = sd_journal_open_directory(&j, t, 0); assert_se(r == 0); + assert_se(sd_journal_seek_head(j) == 0); + assert_se(j->current_location.type == LOCATION_HEAD); + + r = safe_fork("(journal-fork-test)", FORK_WAIT|FORK_LOG, NULL); + if (r == 0) { + assert_se(j); + assert_se(sd_journal_get_realtime_usec(j, NULL) == -ECHILD); + assert_se(sd_journal_seek_tail(j) == -ECHILD); + assert_se(j->current_location.type == LOCATION_HEAD); + sd_journal_close(j); + _exit(EXIT_SUCCESS); + } + + assert_se(r >= 0); + sd_journal_close(j); j = NULL; |