From df8701a3f275aee7f898041285aeb24947c1e451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 8 Jun 2018 13:52:22 +0200 Subject: [PATCH] journal: store the original syslog input as SYSLOG_RAW= This allows the original stream to be recreated and/or verified. The new field is written if any stripping was done or if the input message contained embeded NULs. $ printf '<13>Sep 15 15:07:58 HOST: x\0y' | nc -w1 -u -U /run/systemd/journal/dev-log $ journalctl -o json-pretty ... { ... "MESSAGE" : "x", "SYSLOG_RAW" : [ 60, 49, 51, 62, 83, 101, 112, 32, 49, 53, 32, 49, 53, 58, 48, 55, 58, 53, 56, 32, 72, 79, 83, 84, 58, 32, 120, 0, 121 ] } $ journalctl -o export ... | cat -v ... MESSAGE=x SYSLOG_RAW ^]^@^@^@^@^@^@^@<13>Sep 15 15:07:58 HOST: x^@y This mostly fixes #4863. --- man/systemd.journal-fields.xml | 15 +++++++++++++++ src/journal/journald-syslog.c | 21 ++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml index c079274c32..aeb5367d24 100644 --- a/man/systemd.journal-fields.xml +++ b/man/systemd.journal-fields.xml @@ -112,7 +112,22 @@ see program_invocation_short_name3.) + + + SYSLOG_RAW= + + The original contents of the syslog line as received in the syslog + datagram. This field is only included if the MESSAGE= + field was modified compared to the original payload. This happens when the + message contains leading or trailing whitespace (trailing and leading + whitespace is stripped), or it contains an embedded + NUL byte (the NUL byte and + anything after it is not included). Thus, the original syslog line is + either stored as SYSLOG_RAW= or it can be recreated + based on the stored priority, timestamp, hostname, and the message payload + stored in MESSAGE=. + diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index ea50bd766a..e2794ec30f 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -311,6 +311,7 @@ void server_process_syslog_message( ClientContext *context = NULL; struct iovec *iovec; size_t n = 0, m, i, leading_ws; + bool store_raw; assert(s); assert(buf); @@ -345,6 +346,10 @@ void server_process_syslog_message( t[i - leading_ws] = 0; } + /* We will add the SYSLOG_RAW= field when we stripped anything + * _or_ if the input message contained NUL bytes. */ + store_raw = msg != buf || strlen(msg) != raw_len; + syslog_parse_priority(&msg, &priority, true); if (!client_context_test_priority(context, priority)) @@ -365,7 +370,7 @@ void server_process_syslog_message( if (s->forward_to_wall) server_forward_wall(s, priority, identifier, msg, ucred); - m = N_IOVEC_META_FIELDS + 6 + client_context_extra_fields_n_iovec(context); + m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(context); iovec = newa(struct iovec, m); iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog"); @@ -389,8 +394,18 @@ void server_process_syslog_message( } message = strjoina("MESSAGE=", msg); - if (message) - iovec[n++] = IOVEC_MAKE_STRING(message); + iovec[n++] = IOVEC_MAKE_STRING(message); + + if (store_raw) { + const size_t hlen = strlen("SYSLOG_RAW="); + char *t; + + t = newa(char, hlen + raw_len); + memcpy(t, "SYSLOG_RAW=", hlen); + memcpy(t + hlen, buf, raw_len); + + iovec[n++] = IOVEC_MAKE(t, hlen + raw_len); + } server_dispatch_message(s, iovec, n, m, context, tv, priority, 0); }