From fbee22c2373db393f796fb2942ecbb5fa4ddbeb7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 7 Dec 2024 04:08:59 +0900 Subject: journalctl: show coredumps again when --unit= is specified This is a revised version of cbd5f5d7d6d652d52a18170123f5d08baf7e9862, which is reverted by 560412148fa62d779ea522d43960dd3acd44b261. The filter condition for _UID= field was added by fdcd37df3b97abc381c7b7a29b81cc013c7a3230. However, after 888e378da2dbf4520e68a9d7e59712a3cd5a830f, coredumps for system services are stored by systemd-coredump user. Hence, _UID=0 does not match anything anymore. When we are reading the system journal, let's set _UID=, then we can show coredumps for system services again. When we are reading an external journal, then the uid of systemd-coredump may be different from the one on the current system, so let's drop the filter condition for _UID= in that case. --- src/journal/journalctl-filter.c | 15 ++++++++---- src/shared/logs-show.c | 51 +++++++++++++++++++++++++++++++++-------- src/shared/logs-show.h | 16 +++++++++---- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/src/journal/journalctl-filter.c b/src/journal/journalctl-filter.c index ab65a51451..1c6348574c 100644 --- a/src/journal/journalctl-filter.c +++ b/src/journal/journalctl-filter.c @@ -135,6 +135,7 @@ static int get_possible_units( static int add_units(sd_journal *j) { _cleanup_strv_free_ char **patterns = NULL; bool added = false; + MatchUnitFlag flags = MATCH_UNIT_ALL; int r; assert(j); @@ -142,6 +143,12 @@ static int add_units(sd_journal *j) { if (strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) return 0; + /* When --directory/-D, --root, --file/-i, or --machine/-M is specified, the opened journal file may + * be external, and the uid of the systemd-coredump user that generates the coredump entries may be + * different from the one in the current host. Let's relax the filter condition in such cases. */ + if (arg_directory || arg_root || arg_file_stdin || arg_file || arg_machine) + flags &= ~MATCH_UNIT_COREDUMP_UID; + STRV_FOREACH(i, arg_system_units) { _cleanup_free_ char *u = NULL; @@ -154,7 +161,7 @@ static int add_units(sd_journal *j) { if (r < 0) return r; } else { - r = add_matches_for_unit(j, u); + r = add_matches_for_unit_full(j, flags, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); @@ -173,7 +180,7 @@ static int add_units(sd_journal *j) { return r; SET_FOREACH(u, units) { - r = add_matches_for_unit(j, u); + r = add_matches_for_unit_full(j, flags, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); @@ -197,7 +204,7 @@ static int add_units(sd_journal *j) { if (r < 0) return r; } else { - r = add_matches_for_user_unit(j, u); + r = add_matches_for_user_unit_full(j, flags, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); @@ -216,7 +223,7 @@ static int add_units(sd_journal *j) { return r; SET_FOREACH(u, units) { - r = add_matches_for_user_unit(j, u); + r = add_matches_for_user_unit_full(j, flags, u); if (r < 0) return r; r = sd_journal_add_disjunction(j); diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 0b28ce4117..2289b83a15 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -37,6 +37,7 @@ #include "strv.h" #include "terminal-util.h" #include "time-util.h" +#include "user-util.h" #include "utf8.h" #include "web-util.h" @@ -1627,7 +1628,39 @@ int add_matches_for_invocation_id(sd_journal *j, sd_id128_t id) { return r; } -int add_matches_for_unit_full(sd_journal *j, bool all, const char *unit) { +static int add_matches_for_coredump_uid(sd_journal *j, MatchUnitFlag flags, const char *unit) { + static uid_t cached_uid = 0; + int r; + + assert(j); + assert(unit); + + if (!FLAGS_SET(flags, MATCH_UNIT_COREDUMP_UID)) + return 0; + + if (cached_uid == 0) { + const char *user = "systemd-coredump"; + + r = get_user_creds(&user, &cached_uid, NULL, NULL, NULL, 0); + if (r < 0) { + log_debug_errno(r, "Failed to resolve systemd-coredump user, ignoring: %m"); + cached_uid = UID_INVALID; + } else if (cached_uid == 0) /* Huh? Let's handle that gracefully. */ + cached_uid = UID_INVALID; + } + + if (!uid_is_valid(cached_uid)) + return 0; + + r = journal_add_matchf(j, "_UID="UID_FMT, cached_uid); + if (r < 0) + return r; + + /* for systemd-coredump older than 888e378da2dbf4520e68a9d7e59712a3cd5a830f */ + return sd_journal_add_match(j, "_UID=0", SIZE_MAX); +} + +int add_matches_for_unit_full(sd_journal *j, MatchUnitFlag flags, const char *unit) { int r; assert(j); @@ -1648,16 +1681,16 @@ int add_matches_for_unit_full(sd_journal *j, bool all, const char *unit) { (r = journal_add_match_pair(j, "OBJECT_SYSTEMD_UNIT", unit)) ); - if (r == 0 && all) + if (r == 0 && FLAGS_SET(flags, MATCH_UNIT_COREDUMP)) (void) ( /* Look for coredumps of the service */ (r = sd_journal_add_disjunction(j)) || (r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR, SIZE_MAX)) || - (r = sd_journal_add_match(j, "_UID=0", SIZE_MAX)) || + (r = add_matches_for_coredump_uid(j, flags, unit)) || (r = journal_add_match_pair(j, "COREDUMP_UNIT", unit)) ); - if (r == 0 && all && endswith(unit, ".slice")) + if (r == 0 && FLAGS_SET(flags, MATCH_UNIT_SLICE) && endswith(unit, ".slice")) /* Show all messages belonging to a slice */ (void) ( (r = sd_journal_add_disjunction(j)) || @@ -1667,7 +1700,7 @@ int add_matches_for_unit_full(sd_journal *j, bool all, const char *unit) { return r; } -int add_matches_for_user_unit_full(sd_journal *j, bool all, const char *unit) { +int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, const char *unit) { uid_t uid = getuid(); int r; @@ -1691,7 +1724,7 @@ int add_matches_for_user_unit_full(sd_journal *j, bool all, const char *unit) { (r = sd_journal_add_match(j, "_UID=0", SIZE_MAX)) ); - if (r == 0 && all) + if (r == 0 && FLAGS_SET(flags, MATCH_UNIT_COREDUMP)) (void) ( /* Look for coredumps of the service */ (r = sd_journal_add_disjunction(j)) || @@ -1700,7 +1733,7 @@ int add_matches_for_user_unit_full(sd_journal *j, bool all, const char *unit) { (r = sd_journal_add_match(j, "_UID=0", SIZE_MAX)) ); - if (r == 0 && all && endswith(unit, ".slice")) + if (r == 0 && FLAGS_SET(flags, MATCH_UNIT_SLICE) && endswith(unit, ".slice")) /* Show all messages belonging to a slice */ (void) ( (r = sd_journal_add_disjunction(j)) || @@ -1907,10 +1940,10 @@ static int set_matches_for_discover_id( return add_matches_for_invocation_id(j, id); if (type == LOG_SYSTEM_UNIT_INVOCATION_ID) - return add_matches_for_unit_full(j, /* all = */ false, unit); + 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, /* all = */ false, unit); + return add_matches_for_user_unit_full(j, /* flags = */ 0, unit); return -EINVAL; } diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index ca35aa93f5..4156c9c283 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -56,13 +56,21 @@ int add_match_this_boot(sd_journal *j, const char *machine); int add_matches_for_invocation_id(sd_journal *j, sd_id128_t id); -int add_matches_for_unit_full(sd_journal *j, bool all, const char *unit); +typedef enum MatchUnitFlag { + MATCH_UNIT_SLICE = 1 << 0, + MATCH_UNIT_COREDUMP = 1 << 1, + MATCH_UNIT_COREDUMP_UID = 1 << 2, + + MATCH_UNIT_ALL = MATCH_UNIT_SLICE | MATCH_UNIT_COREDUMP | MATCH_UNIT_COREDUMP_UID, +} MatchUnitFlag; + +int add_matches_for_unit_full(sd_journal *j, MatchUnitFlag flags, const char *unit); static inline int add_matches_for_unit(sd_journal *j, const char *unit) { - return add_matches_for_unit_full(j, true, unit); + return add_matches_for_unit_full(j, MATCH_UNIT_ALL, unit); } -int add_matches_for_user_unit_full(sd_journal *j, bool all, const char *unit); +int add_matches_for_user_unit_full(sd_journal *j, MatchUnitFlag flags, 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, true, unit); + return add_matches_for_user_unit_full(j, MATCH_UNIT_ALL, unit); } int show_journal_by_unit( -- cgit v1.2.3