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);
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;
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);
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);
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);
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);
#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
+#include "user-util.h"
#include "utf8.h"
#include "web-util.h"
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);
(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)) ||
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;
(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)) ||
(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)) ||
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;
}
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(