diff --git a/TODO b/TODO index c54209c708..31634a9759 100644 --- a/TODO +++ b/TODO @@ -967,7 +967,6 @@ Features: * Varlinkification of the following command line tools, to open them up to other programs via IPC: - - bootctl - coredumpcl - systemd-bless-boot - systemd-measure diff --git a/meson.build b/meson.build index 1143181131..b50466dcfd 100644 --- a/meson.build +++ b/meson.build @@ -895,7 +895,6 @@ foreach option : ['adm-gid', 'video-gid', 'wheel-gid', 'systemd-journal-gid', - 'systemd-journal-uid', 'systemd-network-uid', 'systemd-resolve-uid', 'systemd-timesync-uid'] diff --git a/meson_options.txt b/meson_options.txt index 16d7f69611..c1af7ce237 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -328,8 +328,6 @@ option('wheel-gid', type : 'integer', value : 0, description : 'soft-static allocation for the "wheel" group') option('systemd-journal-gid', type : 'integer', value : 0, description : 'soft-static allocation for the systemd-journal group') -option('systemd-journal-uid', type : 'integer', value : 0, - description : 'soft-static allocation for the systemd-journal user') option('systemd-network-uid', type : 'integer', value : 0, description : 'soft-static allocation for the systemd-network user') option('systemd-resolve-uid', type : 'integer', value : 0, diff --git a/src/basic/basic-forward.h b/src/basic/basic-forward.h index ef616dc7a9..1ca9ecfeff 100644 --- a/src/basic/basic-forward.h +++ b/src/basic/basic-forward.h @@ -97,6 +97,7 @@ typedef enum RuntimeScope RuntimeScope; typedef enum TimestampStyle TimestampStyle; typedef enum UnitActiveState UnitActiveState; typedef enum UnitDependency UnitDependency; +typedef enum UnitNameMangle UnitNameMangle; typedef enum UnitType UnitType; typedef enum WaitFlags WaitFlags; diff --git a/src/journal/journalctl-filter.c b/src/journal/journalctl-filter.c index 308f735477..0430f24ce9 100644 --- a/src/journal/journalctl-filter.c +++ b/src/journal/journalctl-filter.c @@ -9,6 +9,7 @@ #include "chase.h" #include "devnum-util.h" #include "fileio.h" +#include "glob-util.h" #include "journal-internal.h" #include "journalctl.h" #include "journalctl-filter.h" @@ -71,6 +72,116 @@ static int add_dmesg(sd_journal *j) { return sd_journal_add_conjunction(j); } +int journal_add_unit_matches( + sd_journal *j, + MatchUnitFlag flags, + UnitNameMangle mangle_flags, + char * const *system_units, + uid_t uid, + char * const *user_units) { + + _cleanup_strv_free_ char **patterns = NULL; + bool added = false; + int r; + + assert(j); + + if (strv_isempty(system_units) && strv_isempty(user_units)) + return 0; + + STRV_FOREACH(i, system_units) { + _cleanup_free_ char *u = NULL; + + r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | mangle_flags, &u); + if (r < 0) + return r; + + if (string_is_glob(u)) { + r = strv_consume(&patterns, TAKE_PTR(u)); + if (r < 0) + return r; + } else { + r = add_matches_for_unit_full(j, flags, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + added = true; + } + } + + if (!strv_isempty(patterns)) { + _cleanup_set_free_ Set *units = NULL; + + r = get_possible_units(j, SYSTEM_UNITS_FULL, patterns, &units); + if (r < 0) + return r; + + char *u; + SET_FOREACH(u, units) { + r = add_matches_for_unit_full(j, flags, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + added = true; + } + } + + patterns = strv_free(patterns); + + STRV_FOREACH(i, user_units) { + _cleanup_free_ char *u = NULL; + + r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | mangle_flags, &u); + if (r < 0) + return r; + + if (string_is_glob(u)) { + r = strv_consume(&patterns, TAKE_PTR(u)); + if (r < 0) + return r; + } else { + r = add_matches_for_user_unit_full(j, flags, uid, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + added = true; + } + } + + + if (!strv_isempty(patterns)) { + _cleanup_set_free_ Set *units = NULL; + + r = get_possible_units(j, USER_UNITS_FULL, patterns, &units); + if (r < 0) + return r; + + char *u; + SET_FOREACH(u, units) { + r = add_matches_for_user_unit_full(j, flags, uid, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + added = true; + } + } + + /* Complain if the user request matches but nothing whatsoever was found, since otherwise everything + * would be matched. */ + if (!added) + return -ENODATA; + + return sd_journal_add_conjunction(j); +} + static int add_units(sd_journal *j) { MatchUnitFlag flags = MATCH_UNIT_ALL; @@ -82,7 +193,9 @@ static int add_units(sd_journal *j) { if (arg_directory || arg_root || arg_file_stdin || arg_file || arg_machine) flags &= ~MATCH_UNIT_COREDUMP_UID; - return journal_add_unit_matches(j, flags, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, arg_system_units, arg_user_units); + return journal_add_unit_matches(j, flags, arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + arg_system_units, + UID_INVALID, arg_user_units); } static int add_syslog_identifier(sd_journal *j) { diff --git a/src/journal/journalctl-filter.h b/src/journal/journalctl-filter.h index dc9474c0f0..95b4aeaf04 100644 --- a/src/journal/journalctl-filter.h +++ b/src/journal/journalctl-filter.h @@ -3,4 +3,12 @@ #include "shared-forward.h" +int journal_add_unit_matches( + sd_journal *j, + MatchUnitFlag flags, + UnitNameMangle mangle_flags, + char * const *system_units, + uid_t uid, + char * const *user_units); + int add_filters(sd_journal *j, char **matches); diff --git a/src/journal/journalctl-util.c b/src/journal/journalctl-util.c index 68761c83c9..aedb2da20d 100644 --- a/src/journal/journalctl-util.c +++ b/src/journal/journalctl-util.c @@ -177,108 +177,6 @@ int get_possible_units( return 0; } -int journal_add_unit_matches(sd_journal *j, MatchUnitFlag flags, UnitNameMangle mangle_flags, char **system_units, char **user_units) { - _cleanup_strv_free_ char **patterns = NULL; - bool added = false; - int r; - - assert(j); - - if (strv_isempty(system_units) && strv_isempty(user_units)) - return 0; - - STRV_FOREACH(i, system_units) { - _cleanup_free_ char *u = NULL; - - r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | mangle_flags, &u); - if (r < 0) - return r; - - if (string_is_glob(u)) { - r = strv_consume(&patterns, TAKE_PTR(u)); - if (r < 0) - return r; - } else { - r = add_matches_for_unit_full(j, flags, u); - if (r < 0) - return r; - r = sd_journal_add_disjunction(j); - if (r < 0) - return r; - added = true; - } - } - - if (!strv_isempty(patterns)) { - _cleanup_set_free_ Set *units = NULL; - - r = get_possible_units(j, SYSTEM_UNITS_FULL, patterns, &units); - if (r < 0) - return r; - - char *u; - SET_FOREACH(u, units) { - r = add_matches_for_unit_full(j, flags, u); - if (r < 0) - return r; - r = sd_journal_add_disjunction(j); - if (r < 0) - return r; - added = true; - } - } - - patterns = strv_free(patterns); - - STRV_FOREACH(i, user_units) { - _cleanup_free_ char *u = NULL; - - r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | mangle_flags, &u); - if (r < 0) - return r; - - if (string_is_glob(u)) { - r = strv_consume(&patterns, TAKE_PTR(u)); - if (r < 0) - return r; - } else { - r = add_matches_for_user_unit_full(j, flags, u); - if (r < 0) - return r; - r = sd_journal_add_disjunction(j); - if (r < 0) - return r; - added = true; - } - } - - if (!strv_isempty(patterns)) { - _cleanup_set_free_ Set *units = NULL; - - r = get_possible_units(j, USER_UNITS_FULL, patterns, &units); - if (r < 0) - return r; - - char *u; - SET_FOREACH(u, units) { - r = add_matches_for_user_unit_full(j, flags, u); - if (r < 0) - return r; - r = sd_journal_add_disjunction(j); - if (r < 0) - return r; - added = true; - } - } - - /* Complain if the user request matches but nothing whatsoever was found, since otherwise everything - * would be matched. */ - if (!added) - return -ENODATA; - - return sd_journal_add_conjunction(j); -} - int acquire_unit(sd_journal *j, const char *option_name, const char **ret_unit, LogIdType *ret_type) { size_t n; int r; diff --git a/src/journal/journalctl-util.h b/src/journal/journalctl-util.h index 0b4993053a..f237aab2b0 100644 --- a/src/journal/journalctl-util.h +++ b/src/journal/journalctl-util.h @@ -3,7 +3,6 @@ #include "shared-forward.h" #include "logs-show.h" -#include "unit-name.h" /* The lists below are supposed to return the superset of unit names possibly matched by rules added with * add_matches_for_unit() and add_matches_for_user_unit(). */ @@ -32,6 +31,5 @@ int acquire_journal(sd_journal **ret); bool journal_boot_has_effect(sd_journal *j); int journal_acquire_boot(sd_journal *j); int get_possible_units(sd_journal *j, const char *fields, char * const *patterns, Set **ret); -int journal_add_unit_matches(sd_journal *j, MatchUnitFlag flags, UnitNameMangle mangle_flags, char **system_units, char **user_units); int acquire_unit(sd_journal *j, const char *option_name, const char **ret_unit, LogIdType *ret_type); int journal_acquire_invocation(sd_journal *j); diff --git a/src/journal/journalctl-varlink-server.c b/src/journal/journalctl-varlink-server.c index e78aa16be2..f44e2a807c 100644 --- a/src/journal/journalctl-varlink-server.c +++ b/src/journal/journalctl-varlink-server.c @@ -4,25 +4,30 @@ #include "sd-varlink.h" #include "journal-internal.h" -#include "journalctl-util.h" +#include "journalctl.h" +#include "journalctl-filter.h" #include "journalctl-varlink-server.h" #include "json-util.h" -#include "log.h" #include "logs-show.h" #include "output-mode.h" +#include "runtime-scope.h" #include "strv.h" +#include "unit-name.h" /* IWYU pragma: keep */ +#include "user-util.h" #include "varlink-util.h" typedef struct GetEntriesParameters { char **units; char **user_units; const char *namespace; + uid_t uid; int priority; uint64_t limit; } GetEntriesParameters; static void get_entries_parameters_done(GetEntriesParameters *p) { assert(p); + p->units = strv_free(p->units); p->user_units = strv_free(p->user_units); } @@ -31,6 +36,7 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl static const sd_json_dispatch_field dispatch_table[] = { { "units", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(GetEntriesParameters, units), 0 }, + { "uid", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uid_gid, offsetof(GetEntriesParameters, uid), 0 }, { "userUnits", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(GetEntriesParameters, user_units), 0 }, { "namespace", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(GetEntriesParameters, namespace), 0 }, { "priority", _SD_JSON_VARIANT_TYPE_INVALID, json_dispatch_log_level, offsetof(GetEntriesParameters, priority), 0 }, @@ -39,6 +45,7 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl }; _cleanup_(get_entries_parameters_done) GetEntriesParameters p = { + .uid = UID_INVALID, .priority = -1, }; _cleanup_(sd_journal_closep) sd_journal *j = NULL; @@ -51,23 +58,26 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl if (r != 0) return r; + if (arg_varlink_runtime_scope == RUNTIME_SCOPE_SYSTEM && p.user_units && !uid_is_valid(p.uid)) + return sd_varlink_error_invalid_parameter_name(link, "uid"); + /* systemd ships with sensible defaults for the system/user services and the socket permissions so we * do not need to do extra sd_varlink_get_peer_uid() or policykit checks here */ r = sd_journal_open_namespace(&j, p.namespace, SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_ASSUME_IMMUTABLE); if (r < 0) - return log_error_errno(r, "Failed to open journal: %m"); + return r; - r = journal_add_unit_matches(j, MATCH_UNIT_ALL, /* mangle_flags= */ 0, p.units, p.user_units); + r = journal_add_unit_matches(j, MATCH_UNIT_ALL, /* mangle_flags= */ 0, p.units, p.uid, p.user_units); if (r == -ENODATA) - return sd_varlink_error(link, SD_VARLINK_ERROR_INVALID_PARAMETER, NULL); + return sd_varlink_error(link, "io.systemd.JournalAccess.NoMatches", NULL); if (r < 0) - return log_error_errno(r, "Failed to add unit matches: %m"); + return r; if (p.priority >= 0) { for (int i = 0; i <= p.priority; i++) { r = journal_add_matchf(j, "PRIORITY=%d", i); if (r < 0) - return log_error_errno(r, "Failed to add priority match: %m"); + return r; } r = sd_journal_add_conjunction(j); @@ -78,7 +88,7 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl /* this simulates "journalctl -n $p.limit" */ r = sd_journal_seek_tail(j); if (r < 0) - return log_error_errno(r, "Failed to seek to tail: %m"); + return r; /* FIXME: this restriction should be removed eventually */ if (p.limit > 10000) @@ -86,6 +96,10 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl uint64_t n = p.limit == 0 ? 100 : p.limit; + r = sd_journal_previous_skip(j, n + 1); + if (r < 0) + return r; + r = varlink_set_sentinel(link, "io.systemd.JournalAccess.NoEntries"); if (r < 0) return r; @@ -93,9 +107,9 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl for (uint64_t i = 0; i < n; i++) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *entry = NULL; - r = sd_journal_previous(j); + r = sd_journal_next(j); if (r < 0) - return log_error_errno(r, "Failed to iterate journal: %m"); + return r; if (r == 0) break; @@ -105,7 +119,7 @@ int vl_method_get_entries(sd_varlink *link, sd_json_variant *parameters, sd_varl if (r == 0) continue; /* skip corrupted entry */ - r = sd_varlink_replybo(link, SD_JSON_BUILD_PAIR("entry", SD_JSON_BUILD_VARIANT(entry))); + r = sd_varlink_replybo(link, SD_JSON_BUILD_PAIR_VARIANT("entry", entry)); if (r < 0) return r; } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 82bf6b8894..b25827961f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -30,6 +30,7 @@ #include "parse-util.h" #include "pcre2-util.h" #include "pretty-print.h" +#include "runtime-scope.h" #include "set.h" #include "static-destruct.h" #include "string-table.h" @@ -111,7 +112,9 @@ pcre2_code *arg_compiled_pattern = NULL; PatternCompileCase arg_case = PATTERN_COMPILE_CASE_AUTO; ImagePolicy *arg_image_policy = NULL; bool arg_synchronize_on_exit = false; + static bool arg_varlink = false; +RuntimeScope arg_varlink_runtime_scope = _RUNTIME_SCOPE_INVALID; STATIC_DESTRUCTOR_REGISTER(arg_cursor, freep); STATIC_DESTRUCTOR_REGISTER(arg_cursor_file, freep); @@ -486,7 +489,35 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m"); if (r > 0) { arg_varlink = true; - arg_pager_flags |= PAGER_DISABLE; + + static const struct option varlink_options[] = { + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + {} + }; + + while ((c = getopt_long(argc, argv, "", varlink_options, NULL)) >= 0) + + switch (c) { + + case ARG_SYSTEM: + arg_varlink_runtime_scope = RUNTIME_SCOPE_SYSTEM; + break; + + case ARG_USER: + arg_varlink_runtime_scope = RUNTIME_SCOPE_USER; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached(); + } + + if (arg_varlink_runtime_scope < 0) + return log_error_errno(arg_varlink_runtime_scope, "Cannot run in Varlink mode with no runtime scope specified."); + return 1; } diff --git a/src/journal/journalctl.h b/src/journal/journalctl.h index 79ffe03464..090e338249 100644 --- a/src/journal/journalctl.h +++ b/src/journal/journalctl.h @@ -94,3 +94,6 @@ extern bool arg_synchronize_on_exit; static inline bool arg_lines_needs_seek_end(void) { return arg_lines >= 0 && !arg_lines_oldest; } + +/* Only used for varlink server invocation */ +extern RuntimeScope arg_varlink_runtime_scope; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 7fa8935af3..3666c16398 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -1193,17 +1193,20 @@ static int update_json_data_split( return update_json_data(h, flags, name, eq + 1, size - fieldlen - 1); } -int journal_entry_to_json(sd_journal *j, OutputFlags flags, const Set *output_fields, sd_json_variant **ret) { +int journal_entry_to_json( + sd_journal *j, + OutputFlags flags, + const Set *output_fields, + sd_json_variant **ret) { char usecbuf[CONST_MAX(DECIMAL_STR_MAX(usec_t), DECIMAL_STR_MAX(uint64_t))]; - _cleanup_(sd_json_variant_unrefp) sd_json_variant *object = NULL; - _cleanup_hashmap_free_ Hashmap *h = NULL; sd_id128_t journal_boot_id, seqnum_id; _cleanup_free_ char *cursor = NULL; usec_t realtime, monotonic; - sd_json_variant **array = NULL; - JsonData *d; uint64_t seqnum; + const char *corrupted_what = NULL; + _cleanup_hashmap_free_ Hashmap *h = NULL; + _cleanup_free_ sd_json_variant **array = NULL; size_t n = 0; int r; @@ -1214,32 +1217,32 @@ int journal_entry_to_json(sd_journal *j, OutputFlags flags, const Set *output_fi r = sd_journal_get_cursor(j, &cursor); if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) { - log_debug_errno(r, "Unable to determine cursor of entry, assuming bad or partially written entry: %m"); - return 0; + corrupted_what = "cursor"; + goto corrupted_skip; } if (r < 0) return log_error_errno(r, "Failed to get cursor: %m"); r = sd_journal_get_realtime_usec(j, &realtime); if (r == -EBADMSG) { - log_debug_errno(r, "Unable to read realtime timestamp of entry, assuming bad or partially written entry: %m"); - return 0; + corrupted_what = "realtime timestamp"; + goto corrupted_skip; } if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); r = sd_journal_get_monotonic_usec(j, &monotonic, &journal_boot_id); if (r == -EBADMSG) { - log_debug_errno(r, "Unable to read monotonic timestamp of entry, assuming bad or partially written entry: %m"); - return 0; + corrupted_what = "monotonic timestamp"; + goto corrupted_skip; } if (r < 0) return log_error_errno(r, "Failed to get monotonic timestamp: %m"); r = sd_journal_get_seqnum(j, &seqnum, &seqnum_id); if (r == -EBADMSG) { - log_debug_errno(r, "Unable to read sequence number of entry, assuming bad or partially written entry: %m"); - return 0; + corrupted_what = "sequence number"; + goto corrupted_skip; } if (r < 0) return log_error_errno(r, "Failed to get seqnum: %m"); @@ -1294,29 +1297,32 @@ int journal_entry_to_json(sd_journal *j, OutputFlags flags, const Set *output_fi return r; } - array = new(sd_json_variant*, hashmap_size(h)*2); + array = new(sd_json_variant*, hashmap_size(h) * 2); if (!array) return log_oom(); - CLEANUP_ARRAY(array, n, sd_json_variant_unref_many); - + JsonData *d; HASHMAP_FOREACH(d, h) { assert(sd_json_variant_elements(d->values) > 0); - array[n++] = sd_json_variant_ref(d->name); + array[n++] = d->name; if (sd_json_variant_elements(d->values) == 1) - array[n++] = sd_json_variant_ref(sd_json_variant_by_index(d->values, 0)); + array[n++] = sd_json_variant_by_index(d->values, 0); else - array[n++] = sd_json_variant_ref(d->values); + array[n++] = d->values; } - r = sd_json_variant_new_object(&object, array, n); + r = sd_json_variant_new_object(ret, array, n); if (r < 0) return log_error_errno(r, "Failed to allocate JSON object: %m"); - *ret = TAKE_PTR(object); return 1; + +corrupted_skip: + log_debug_errno(r, "Unable to determine %s of entry, assuming bad or partially written entry: %m", ASSERT_PTR(corrupted_what)); + *ret = NULL; + return 0; } static int output_json( @@ -1338,9 +1344,9 @@ static int output_json( return r; return sd_json_variant_dump(object, - output_mode_to_json_format_flags(mode) | - (FLAGS_SET(flags, OUTPUT_COLOR) ? SD_JSON_FORMAT_COLOR : 0), - f, NULL); + output_mode_to_json_format_flags(mode) | + (FLAGS_SET(flags, OUTPUT_COLOR) ? SD_JSON_FORMAT_COLOR : 0), + f, NULL); } static int output_cat_field( @@ -1761,13 +1767,15 @@ int add_matches_for_unit_full(sd_journal *j, MatchUnitFlag flags, const char *un return r; } -int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, const char *unit) { - uid_t uid = getuid(); +int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, uid_t uid, const char *unit) { int r; assert(j); assert(unit); + if (uid == UID_INVALID) + uid = getuid(); + (void) ( /* Look for messages from the user service itself */ (r = journal_add_match_pair(j, "_SYSTEMD_USER_UNIT", unit)) || @@ -2004,7 +2012,7 @@ static int set_matches_for_discover_id( return add_matches_for_unit_full(j, /* flags= */ 0, unit); if (type == LOG_USER_UNIT_INVOCATION_ID) - return add_matches_for_user_unit_full(j, /* flags= */ 0, unit); + return add_matches_for_user_unit_full(j, /* flags= */ 0, UID_INVALID, unit); return -EINVAL; } diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index e2886d69cd..5108941f79 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -57,9 +57,9 @@ int add_matches_for_unit_full(sd_journal *j, MatchUnitFlag flags, const char *un static inline int add_matches_for_unit(sd_journal *j, const char *unit) { return add_matches_for_unit_full(j, MATCH_UNIT_ALL, unit); } -int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, const char *unit); +int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, uid_t uid, const char *unit); static inline int add_matches_for_user_unit(sd_journal *j, const char *unit) { - return add_matches_for_user_unit_full(j, MATCH_UNIT_ALL, unit); + return add_matches_for_user_unit_full(j, MATCH_UNIT_ALL, UID_INVALID, unit); } int show_journal_by_unit( diff --git a/src/shared/shared-forward.h b/src/shared/shared-forward.h index 09ce806ad2..e07b25c056 100644 --- a/src/shared/shared-forward.h +++ b/src/shared/shared-forward.h @@ -26,6 +26,7 @@ typedef enum DnssecMode DnssecMode; typedef enum Fido2EnrollFlags Fido2EnrollFlags; typedef enum KeySourceType KeySourceType; typedef enum LabelFixFlags LabelFixFlags; +typedef enum MatchUnitFlag MatchUnitFlag; typedef enum MountInNamespaceFlags MountInNamespaceFlags; typedef enum NamePolicy NamePolicy; typedef enum OutputFlags OutputFlags; diff --git a/src/shared/varlink-io.systemd.JournalAccess.c b/src/shared/varlink-io.systemd.JournalAccess.c index c9e65c1a4f..b057067079 100644 --- a/src/shared/varlink-io.systemd.JournalAccess.c +++ b/src/shared/varlink-io.systemd.JournalAccess.c @@ -7,6 +7,8 @@ static SD_VARLINK_DEFINE_METHOD_FULL( SD_VARLINK_REQUIRES_MORE, SD_VARLINK_FIELD_COMMENT("Show messages for the specified systemd units (e.g. ['foo.service'])."), SD_VARLINK_DEFINE_INPUT(units, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY), + SD_VARLINK_FIELD_COMMENT("UID to match user units for"), + SD_VARLINK_DEFINE_INPUT(uid, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("Show messages for the specified user units (e.g. ['foo.service'])."), SD_VARLINK_DEFINE_INPUT(userUnits, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY), SD_VARLINK_FIELD_COMMENT("If specified, shows the log data of the specified namespace, otherwise the default namespace."), @@ -16,8 +18,9 @@ static SD_VARLINK_DEFINE_METHOD_FULL( SD_VARLINK_FIELD_COMMENT("Maximum number of entries to return. Defaults to 100, capped at 10000."), SD_VARLINK_DEFINE_INPUT(limit, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_FIELD_COMMENT("The journal entry in flat JSON format, matching journalctl --output=json."), - SD_VARLINK_DEFINE_OUTPUT(entry, SD_VARLINK_OBJECT, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_OUTPUT(entry, SD_VARLINK_OBJECT, 0)); +static SD_VARLINK_DEFINE_ERROR(NoMatches); static SD_VARLINK_DEFINE_ERROR(NoEntries); SD_VARLINK_DEFINE_INTERFACE( @@ -26,5 +29,7 @@ SD_VARLINK_DEFINE_INTERFACE( SD_VARLINK_INTERFACE_COMMENT("Journal log read APIs"), SD_VARLINK_SYMBOL_COMMENT("Retrieve journal log entries, optionally filtered by unit, priority, etc."), &vl_method_GetEntries, + SD_VARLINK_SYMBOL_COMMENT("No matches found for specified unit patterns"), + &vl_error_NoMatches, SD_VARLINK_SYMBOL_COMMENT("No journal entries matched the specified filters."), &vl_error_NoEntries); diff --git a/sysusers.d/systemd-journal.conf.in b/sysusers.d/systemd-journal.conf.in index bb1277f2bb..61768b234e 100644 --- a/sysusers.d/systemd-journal.conf.in +++ b/sysusers.d/systemd-journal.conf.in @@ -5,5 +5,4 @@ # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. -g systemd-journal {{SYSTEMD_JOURNAL_GID}} - -u! systemd-journal {{SYSTEMD_JOURNAL_UID}} "systemd Journal" +g systemd-journal {{SYSTEMD_JOURNAL_GID}} - diff --git a/units/systemd-journalctl@.service b/units/systemd-journalctl@.service index 84ac18cbbc..b6111124ef 100644 --- a/units/systemd-journalctl@.service +++ b/units/systemd-journalctl@.service @@ -13,7 +13,10 @@ Documentation=man:journalctl(1) DefaultDependencies=no Conflicts=shutdown.target Before=shutdown.target +RequiresMountsFor=/var/log/journal [Service] -ExecStart=journalctl -User=systemd-journal +ExecStart=journalctl --system +DynamicUser=yes +User=systemd-journal-access +SupplementaryGroups=systemd-journal diff --git a/units/systemd-pcrlock.socket b/units/systemd-pcrlock.socket index e166caf3d8..efb6818683 100644 --- a/units/systemd-pcrlock.socket +++ b/units/systemd-pcrlock.socket @@ -22,6 +22,3 @@ FileDescriptorName=varlink SocketMode=0600 Accept=yes MaxConnectionsPerSource=16 - -[Install] -WantedBy=sockets.target diff --git a/units/user/systemd-journalctl.socket b/units/user/systemd-journalctl.socket index 0ea3a25c90..b8a504f0f3 100644 --- a/units/user/systemd-journalctl.socket +++ b/units/user/systemd-journalctl.socket @@ -17,4 +17,3 @@ Symlinks=%t/varlink/registry/io.systemd.JournalAccess FileDescriptorName=varlink SocketMode=0600 Accept=yes -MaxConnectionsPerSource=16 diff --git a/units/user/systemd-journalctl@.service b/units/user/systemd-journalctl@.service index 04749fdb58..8449baa4c5 100644 --- a/units/user/systemd-journalctl@.service +++ b/units/user/systemd-journalctl@.service @@ -12,4 +12,4 @@ Description=Journal Log Access Service Documentation=man:journalctl(1) [Service] -ExecStart=journalctl +ExecStart=journalctl --user