diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2024-12-06 20:08:59 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2024-12-09 15:18:55 +0100 |
commit | fbee22c2373db393f796fb2942ecbb5fa4ddbeb7 (patch) | |
tree | dd1cea6edfc899ba720f7caf48e10ef3b71855dc | |
parent | systemctl: use correct runtime scope (diff) | |
download | systemd-fbee22c2373db393f796fb2942ecbb5fa4ddbeb7.tar.xz systemd-fbee22c2373db393f796fb2942ecbb5fa4ddbeb7.zip |
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=<systemd-coredump>,
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.
-rw-r--r-- | src/journal/journalctl-filter.c | 15 | ||||
-rw-r--r-- | src/shared/logs-show.c | 51 | ||||
-rw-r--r-- | 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( |