summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2024-12-06 20:08:59 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2024-12-09 15:18:55 +0100
commitfbee22c2373db393f796fb2942ecbb5fa4ddbeb7 (patch)
treedd1cea6edfc899ba720f7caf48e10ef3b71855dc
parentsystemctl: use correct runtime scope (diff)
downloadsystemd-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.c15
-rw-r--r--src/shared/logs-show.c51
-rw-r--r--src/shared/logs-show.h16
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(