Files
infix/patches/sysklogd/2.7.2/0004-syslogd-unescape-Linux-dev-kmsg-messages-before-sani.patch
T
Joachim Wiberg 442b572478 patches/sysklogd: backport fixes
- Allow parenthesis in tag names
- Unescape Linux /dev/kmsg messages for unicode characters

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-20 11:59:59 +01:00

143 lines
4.0 KiB
Diff

From c1c3f253a8963c6e9e41fafcf9b888f3f5a34906 Mon Sep 17 00:00:00 2001
From: Joachim Wiberg <troglobit@gmail.com>
Date: Mon, 3 Nov 2025 13:11:56 +0100
Subject: [PATCH 4/4] syslogd: unescape Linux /dev/kmsg messages before
sanitization
Organization: Wires
Linux's /dev/kmsg interface escapes all non-printable characters and
backslashes using C-style hex encoding (\xHH format). Preventing the
recent UTF-8 sanitization improvements from working correctly, since
UTF-8 sequences arrive as escaped text like "\xe2\x80\x94" rather than
as actual bytes, see [1] for details.
This commit implements "unescaping" of the kernel's C-style format
before applying the UTF-8-aware sanitization. Ensuring that UTF-8
content also in kernel messages is properly preserved when using the
-8 flag.
[1]: https://www.kernel.org/doc/Documentation/ABI/testing/dev-kmsg
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
src/syslogd.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 77 insertions(+), 4 deletions(-)
diff --git a/src/syslogd.c b/src/syslogd.c
index 37e1920..0b6bc30 100644
--- a/src/syslogd.c
+++ b/src/syslogd.c
@@ -155,6 +155,7 @@ static int KernLog = 1; /* Track kernel logs by default */
static int KeepKernFac; /* Keep remotely logged kernel facility */
static int KeepKernTime; /* Keep kernel timestamp, evern after initial read */
static int KeepKernConsole; /* Keep kernel logging to console */
+static int IsLinuxKmsg; /* Set if reading from Linux /dev/kmsg */
static int rotate_opt; /* Set if command line option has been given (wins) */
static off_t RotateSz = 0; /* Max file size (bytes) before rotating, disabled by default */
@@ -651,8 +652,10 @@ int main(int argc, char *argv[])
_PATH_KLOG);
else
kern_console_off();
- } else
+ } else {
+ IsLinuxKmsg = 1;
kern_console_off();
+ }
}
no_klogd:
consfile.f_type = F_CONSOLE;
@@ -1062,6 +1065,61 @@ utf8_valid(const unsigned char *in, size_t len)
return 1;
}
+/*
+ * Unescapes Linux /dev/kmsg messages that use C-style hex encoding.
+ * Converts "\xHH" sequences back to bytes and "\\" back to "\".
+ * Returns the new length of the unescaped string.
+ */
+static size_t kmsg_unescape(char *msg)
+{
+ char *src, *dst;
+ int hi, lo;
+
+ src = dst = msg;
+ while (*src) {
+ if (*src == '\\' && src[1]) {
+ if (src[1] == 'x' && src[2] && src[3]) {
+ /* Decode \xHH */
+ hi = src[2];
+ lo = src[3];
+
+ /* Convert hex digits to values */
+ if (hi >= '0' && hi <= '9')
+ hi = hi - '0';
+ else if (hi >= 'a' && hi <= 'f')
+ hi = hi - 'a' + 10;
+ else if (hi >= 'A' && hi <= 'F')
+ hi = hi - 'A' + 10;
+ else
+ goto copy_literal;
+
+ if (lo >= '0' && lo <= '9')
+ lo = lo - '0';
+ else if (lo >= 'a' && lo <= 'f')
+ lo = lo - 'a' + 10;
+ else if (lo >= 'A' && lo <= 'F')
+ lo = lo - 'A' + 10;
+ else
+ goto copy_literal;
+
+ *dst++ = (char)((hi << 4) | lo);
+ src += 4;
+ continue;
+ } else if (src[1] == '\\') {
+ /* Decode \\ to \ */
+ *dst++ = '\\';
+ src += 2;
+ continue;
+ }
+ }
+copy_literal:
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+
+ return dst - msg;
+}
+
/*
* Removes characters from log messages that are unsafe to display.
* Preserves valid UTF-8 sequences, including BOM, with -8 flag.
@@ -1773,9 +1831,24 @@ void printsys(char *msg)
parsemsg_rfc3164_app_name_procid(&p, &buffer.app_name, &buffer.proc_id);
q = lp;
- while (*p != '\0' && (c = *p++) != '\n' && q < &line[MAXLINE])
- *q++ = c;
- *q = '\0';
+ if (IsLinuxKmsg) {
+ char tmp[MAXLINE + 1];
+ char *t = tmp;
+
+ while (*p != '\0' && *p != '\n' && t < &tmp[MAXLINE])
+ *t++ = *p++;
+ *t = '\0';
+
+ /* Unescape \xHH sequences and \\ */
+ kmsg_unescape(tmp);
+
+ /* Sanitize the unescaped message with UTF-8 support */
+ parsemsg_remove_unsafe_characters(tmp, lp, MAXLINE);
+ } else {
+ while (*p != '\0' && (c = *p++) != '\n' && q < &line[MAXLINE])
+ *q++ = c;
+ *q = '\0';
+ }
logmsg(&buffer);
}
--
2.43.0