]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journalctl: show coredumps again when --unit= is specified
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 6 Dec 2024 19:08:59 +0000 (04:08 +0900)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 9 Dec 2024 14:18:55 +0000 (15:18 +0100)
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.

src/journal/journalctl-filter.c
src/shared/logs-show.c
src/shared/logs-show.h

index ab65a51451ea0f2d7ea27cf64396e7fa4ccd8eef..1c6348574c5f0cfead6351c1903eb380c3dc3984 100644 (file)
@@ -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);
index 0b28ce411734197308b0adc81d60763fc88ff678..2289b83a1506414ab9f503e3295e67216d5c6231 100644 (file)
@@ -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;
 }
index ca35aa93f5ef10b1393c8c7430264e653fe3d08a..4156c9c28308b2de32e3ce53e1c56eefa151e9fd 100644 (file)
@@ -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(