]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lslogins: use sd_journal_get_data() in proper way
authorKarel Zak <kzak@redhat.com>
Thu, 22 Jul 2021 09:03:54 +0000 (11:03 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 22 Jul 2021 09:35:22 +0000 (11:35 +0200)
man sd_journal_get_data:
    The returned data is in a read-only memory map and is only valid until the next invocation
    of sd_journal_get_data().

It means that use data after 3x sd_journal_get_data() is really bad
idea. It also seems better to not assume the fields are zero
terminated as journal API works with void* and size_t to address the
data.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1984704
Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/lslogins.c

index 908d78b11a322fa0f88e21c9e187c6a3810f5b74..cf1b8e7cafb79a3ce6d5103253853d935aa5cbb1 100644 (file)
@@ -1231,14 +1231,28 @@ static void fill_table(const void *u, const VISIT which, const int depth __attri
        }
 }
 #ifdef HAVE_LIBSYSTEMD
+static char *get_journal_data(sd_journal *j, const char *name)
+{
+       const char *data = NULL, *p;
+       size_t len = 0;
+
+       if (sd_journal_get_data(j, name, (const void **) &data, &len) < 0
+           || !data || !len)
+               return NULL;
+
+       /* Get rid of journal entry field identifiers */
+       p = strnchr(data, len, '=');
+       if (!p || !*(p + 1))
+               return NULL;
+       p++;
+
+       return xstrndup(p, len - (p - data));
+}
+
 static void print_journal_tail(const char *journal_path, uid_t uid, size_t len, int time_mode)
 {
        sd_journal *j;
-       char *match, *timestamp;
-       uint64_t x;
-       time_t t;
-       const char *identifier, *pid, *message;
-       size_t identifier_len, pid_len, message_len;
+       char *match;
 
        if (journal_path)
                sd_journal_open_directory(&j, journal_path, 0);
@@ -1252,30 +1266,27 @@ static void print_journal_tail(const char *journal_path, uid_t uid, size_t len,
        sd_journal_previous_skip(j, len);
 
        do {
-               if (0 > sd_journal_get_data(j, "SYSLOG_IDENTIFIER",
-                               (const void **) &identifier, &identifier_len))
-                       goto done;
-               if (0 > sd_journal_get_data(j, "_PID",
-                               (const void **) &pid, &pid_len))
-                       goto done;
-               if (0 > sd_journal_get_data(j, "MESSAGE",
-                               (const void **) &message, &message_len))
-                       goto done;
+               char *id, *pid, *msg, *ts;
+               uint64_t x;
+               time_t t;
 
                sd_journal_get_realtime_usec(j, &x);
                t = x / 1000000;
-               timestamp = make_time(time_mode, t);
-               /* Get rid of journal entry field identifiers */
-               identifier = strchr(identifier, '=') + 1;
-               pid = strchr(pid, '=') + 1;
-               message = strchr(message, '=') + 1;
-
-               fprintf(stdout, "%s %s[%s]: %s\n", timestamp, identifier, pid,
-                       message);
-               free(timestamp);
+               ts = make_time(time_mode, t);
+
+               id = get_journal_data(j, "SYSLOG_IDENTIFIER");
+               pid = get_journal_data(j, "_PID");
+               msg = get_journal_data(j, "MESSAGE");
+
+               if (ts && id && pid && msg)
+                       fprintf(stdout, "%s %s[%s]: %s\n", ts, id, pid, msg);
+
+               free(ts);
+               free(id);
+               free(pid);
+               free(msg);
        } while (sd_journal_next(j));
 
-done:
        free(match);
        sd_journal_flush_matches(j);
        sd_journal_close(j);