mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
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>
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
||||
From 31dfe0d16461d2852f3fc56cb82aed3a23db022f Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 25 Sep 2025 16:48:31 +0200
|
||||
Subject: [PATCH] syslogd: fix UTF-8 handling with -8 flag, for RFC5424
|
||||
Subject: [PATCH 1/4] syslogd: fix UTF-8 handling with -8 flag, for RFC5424
|
||||
compliance
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
From f9b6531430c6485af4697a5868a6f43c93d20419 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Fri, 26 Sep 2025 08:42:57 +0200
|
||||
Subject: [PATCH 2/4] syslogd: fix parentheses handling in RFC 3164 tag parsing
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Organization: Wires
|
||||
|
||||
Some applications use tag names like "(polkit-agent)" which sysklogd do
|
||||
not handle well. This patch aims to address this and also add a bit of
|
||||
logic to normalize such tags:
|
||||
|
||||
- Allow parentheses in tag character set for broader compatibility
|
||||
- Smart parsing: strip surrounding parentheses from complete tags like
|
||||
"(polkit-agent):" → "polkit-agent", while preserving partial parentheses
|
||||
like "app(version):" unchanged
|
||||
- Maintain RFC compliance: both RFC3164 and RFC5424 allow parentheses
|
||||
- Preserve all existing functionality and edge case handling
|
||||
|
||||
Fixes #104
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/syslogd.c | 35 ++++++++++++++++++++++++++++-------
|
||||
1 file changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/syslogd.c b/src/syslogd.c
|
||||
index fa82d98..37e1920 100644
|
||||
--- a/src/syslogd.c
|
||||
+++ b/src/syslogd.c
|
||||
@@ -1309,15 +1309,36 @@ parsemsg_rfc3164_app_name_procid(char **msg, char **app_name, char **procid)
|
||||
m = *msg;
|
||||
|
||||
/* Application name. */
|
||||
- app_name_begin = m;
|
||||
- app_name_length = strspn(m,
|
||||
- "abcdefghijklmnopqrstuvwxyz"
|
||||
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
- "0123456789"
|
||||
- "._-/");
|
||||
+ /* Check if tag is surrounded by parentheses like (polkit-agent) */
|
||||
+ if (*m == '(') {
|
||||
+ char *closing = strchr(m + 1, ')');
|
||||
+ if (closing && (closing[1] == ':' || closing[1] == '[' || isblank(closing[1]) || closing[1] == '\0')) {
|
||||
+ /* Found complete parenthetical tag, strip parentheses */
|
||||
+ app_name_begin = m + 1;
|
||||
+ app_name_length = closing - (m + 1);
|
||||
+ m = closing + 1;
|
||||
+ } else {
|
||||
+ /* Incomplete or malformed, treat normally */
|
||||
+ app_name_begin = m;
|
||||
+ app_name_length = strspn(m,
|
||||
+ "abcdefghijklmnopqrstuvwxyz"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "0123456789"
|
||||
+ "._-/()");
|
||||
+ m += app_name_length;
|
||||
+ }
|
||||
+ } else {
|
||||
+ app_name_begin = m;
|
||||
+ app_name_length = strspn(m,
|
||||
+ "abcdefghijklmnopqrstuvwxyz"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "0123456789"
|
||||
+ "._-/()");
|
||||
+ m += app_name_length;
|
||||
+ }
|
||||
+
|
||||
if (app_name_length == 0)
|
||||
goto bad;
|
||||
- m += app_name_length;
|
||||
|
||||
/* Process identifier (optional). */
|
||||
if (*m == '[') {
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
From 10372296093cc70f3d21b46359a4cfbd8312c968 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Fri, 26 Sep 2025 10:07:45 +0200
|
||||
Subject: [PATCH 3/4] test: verify parenthetical tag parsing
|
||||
Organization: Wires
|
||||
|
||||
Regression test for issue #104.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
test/Makefile.am | 5 +-
|
||||
test/parens.sh | 119 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 122 insertions(+), 2 deletions(-)
|
||||
create mode 100755 test/parens.sh
|
||||
|
||||
diff --git a/test/Makefile.am b/test/Makefile.am
|
||||
index 7162e6c..59a38cf 100644
|
||||
--- a/test/Makefile.am
|
||||
+++ b/test/Makefile.am
|
||||
@@ -3,10 +3,10 @@ EXTRA_DIST += api.sh local.sh unicode.sh remote.sh fwd.sh mark.sh \
|
||||
memleak.sh facility.sh notify.sh rotate_all.sh secure.sh \
|
||||
logger.sh listen.sh sighup.sh tag.sh hostname.sh \
|
||||
property.sh raw.sh regression.sh multicast.sh \
|
||||
- mcast-fwd.sh mcast-iface.sh
|
||||
+ mcast-fwd.sh mcast-iface.sh parens.sh
|
||||
CLEANFILES = *~ *.trs *.log
|
||||
TEST_EXTENSIONS = .sh
|
||||
-TESTS_ENVIRONMENT= unshare -mrun
|
||||
+TESTS_ENVIRONMENT= unshare -mrun --map-auto
|
||||
|
||||
check_PROGRAMS = api
|
||||
api_SOURCES = api.c
|
||||
@@ -30,6 +30,7 @@ TESTS += rotate_all.sh
|
||||
TESTS += secure.sh
|
||||
TESTS += sighup.sh
|
||||
TESTS += tag.sh
|
||||
+TESTS += parens.sh
|
||||
TESTS += hostname.sh
|
||||
TESTS += property.sh
|
||||
TESTS += raw.sh
|
||||
diff --git a/test/parens.sh b/test/parens.sh
|
||||
new file mode 100755
|
||||
index 0000000..43b8744
|
||||
--- /dev/null
|
||||
+++ b/test/parens.sh
|
||||
@@ -0,0 +1,119 @@
|
||||
+#!/bin/sh
|
||||
+# Verify parentheses handling in log tags for RFC3164 messages.
|
||||
+# Regression test for issue #104.
|
||||
+#
|
||||
+. "${srcdir:-.}/lib.sh"
|
||||
+
|
||||
+
|
||||
+MSG1="Failed to execute /usr/bin/pkttyagent: No such file or directory"
|
||||
+MSG2="Normal application message"
|
||||
+MSG3="Version specific message"
|
||||
+MSG4="Service startup message"
|
||||
+
|
||||
+LOGDIR="$DIR/log"
|
||||
+SYSLOG="${LOGDIR}/syslog"
|
||||
+
|
||||
+setup_syslogd()
|
||||
+{
|
||||
+ mkdir -p "$LOGDIR"
|
||||
+ cat <<-EOF >"${CONF}"
|
||||
+ # Log everything for testing
|
||||
+ *.* -$SYSLOG
|
||||
+ EOF
|
||||
+ setup -m0
|
||||
+}
|
||||
+
|
||||
+
|
||||
+extract_tag()
|
||||
+{
|
||||
+ msg="$1"
|
||||
+ actual_line=$(grep "$msg" "$SYSLOG" | tail -1)
|
||||
+ if [ -n "$actual_line" ]; then
|
||||
+ echo "$actual_line" | sed -n 's/.*[0-9][0-9] [^ ]* \([^:]*\):.*/\1/p'
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+show_result()
|
||||
+{
|
||||
+ input="$1"
|
||||
+ expected="$2"
|
||||
+ got="$3"
|
||||
+
|
||||
+ echo "Input: '$input'"
|
||||
+ echo "Expected: '$expected'"
|
||||
+ echo "Got: '$got'"
|
||||
+}
|
||||
+
|
||||
+verify()
|
||||
+{
|
||||
+ input_tag="$1"
|
||||
+ expected_tag="$2"
|
||||
+ msg="$3"
|
||||
+ expected_pattern="${4:-$expected_tag}"
|
||||
+
|
||||
+ actual_tag=$(extract_tag "$msg")
|
||||
+ if [ -n "$actual_tag" ]; then
|
||||
+ show_result "$input_tag" "$expected_tag" "$actual_tag"
|
||||
+ if grep -q "$expected_pattern.*$msg" "$SYSLOG"; then
|
||||
+ return 0
|
||||
+ else
|
||||
+ echo "Log contents:"
|
||||
+ cat "$SYSLOG"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ else
|
||||
+ echo "Message not found in log"
|
||||
+ echo "Log contents:"
|
||||
+ cat "$SYSLOG"
|
||||
+ return 1
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+test_normal_tag()
|
||||
+{
|
||||
+ logger -b -ip user.info -t "normal-app" "$MSG2"
|
||||
+ verify "normal-app" "normal-app" "$MSG2"
|
||||
+}
|
||||
+
|
||||
+test_paren_stripping()
|
||||
+{
|
||||
+ logger -b -ip user.info -t "(polkit-agent)" "$MSG1"
|
||||
+ verify "(polkit-agent)" "polkit-agent" "$MSG1"
|
||||
+}
|
||||
+
|
||||
+test_service_stripping()
|
||||
+{
|
||||
+ logger -b -ip user.info -t "(service-name)" "$MSG4"
|
||||
+ verify "(service-name)" "service-name" "$MSG4"
|
||||
+}
|
||||
+
|
||||
+test_partial_parens()
|
||||
+{
|
||||
+ logger -b -ip user.info -t "app(version)" "$MSG3"
|
||||
+ verify "app(version)" "app(version)" "$MSG3"
|
||||
+}
|
||||
+
|
||||
+test_normal_tag_with_pid()
|
||||
+{
|
||||
+ pid="$$"
|
||||
+
|
||||
+ logger -b -ip user.info -t "normal-app[${pid}]" "$MSG2"
|
||||
+ verify "normal-app[${pid}]" "normal-app[${pid}]" "$MSG2" "normal-app\[${pid}\]"
|
||||
+}
|
||||
+
|
||||
+test_paren_with_pid()
|
||||
+{
|
||||
+ pid="$$"
|
||||
+
|
||||
+ logger -b -ip user.info -t "(polkit-agent)[$pid]" "$MSG1"
|
||||
+ verify "(polkit-agent)[$pid]" "polkit-agent[$pid]" "$MSG1" "polkit-agent\[$pid\]"
|
||||
+}
|
||||
+
|
||||
+
|
||||
+run_step "Set up syslogd for parentheses testing" setup_syslogd
|
||||
+run_step "Test parenthetical tag stripping" test_paren_stripping
|
||||
+run_step "Test normal tag preservation" test_normal_tag
|
||||
+run_step "Test partial parentheses preservation" test_partial_parens
|
||||
+run_step "Test service parenthetical tag" test_service_stripping
|
||||
+run_step "Test parenthetical tag with PID" test_paren_with_pid
|
||||
+run_step "Test normal tag with PID" test_normal_tag_with_pid
|
||||
--
|
||||
2.43.0
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user