]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-rules: drop truncated import output line
authordongshengyuan <545258830@qq.com>
Fri, 10 Jul 2026 08:05:24 +0000 (16:05 +0800)
committerdongshengyuan <545258830@qq.com>
Fri, 10 Jul 2026 08:05:24 +0000 (16:05 +0800)
When IMPORT{program} output was truncated, the code intended to drop
the last incomplete result line before importing properties.

It edited the command buffer instead of the output buffer, so the
incomplete line could still be parsed and imported.

Trim the result buffer and cover the behavior with the existing IMPORT
test.

Follow-up for 6b6e471a325bf149839c5c822b4ae3e66cb1d9a3.

Reproducer:

Configure an IMPORT{program} rule whose output exceeds UDEV_LINE_SIZE
and ends with an incomplete property line, for example:

TRUNCATED_OK=yes
TRUNCATED_BAD=<very long value without terminating newline>

Only TRUNCATED_OK should be imported. Before this fix, the truncation
handler edited the command buffer instead of the output buffer, so
TRUNCATED_BAD could still be parsed from the truncated result.

src/udev/udev-rules.c
test/units/TEST-17-UDEV.IMPORT.sh

index 42f6fde8a089b92fcbf8e2a49fa8eb29957d038c..88f633138e6235e99f16566849bfb8c21db06dd1 100644 (file)
@@ -2482,14 +2482,14 @@ static int udev_rule_apply_token_to_event(
 
                         /* Drop the last line. */
                         bool found = false;
-                        for (char *p = PTR_SUB1(buf + strlen(buf), buf); p; p = PTR_SUB1(p, buf))
+                        for (char *p = PTR_SUB1(result + strlen(result), result); p; p = PTR_SUB1(p, result))
                                 if (strchr(NEWLINE, *p)) {
                                         *p = '\0';
                                         found = true;
                                         break;
                                 }
                         if (!found)
-                                buf[0] = '\0';
+                                result[0] = '\0';
                 }
 
                 r = strv_split_newlines_full(&lines, result, EXTRACT_RETAIN_ESCAPE);
index f09b171066187e1016a0709b193e970ff6d12a56..f2f9a4100eefbf01c58741ac8640750bfbf9ba3a 100755 (executable)
@@ -17,6 +17,17 @@ test -f /run/udev/data/c1:3
 udevadm info /dev/null | grep 'E: HOGE=aa\\x20\\x20\\x20bb' >/dev/null
 udevadm info /dev/null | grep 'E: FOO=\\x20aaa\\x20' >/dev/null
 
+cat >/run/udev/rules.d/50-testsuite.rules <<'EOF'
+SUBSYSTEM=="mem", KERNEL=="null", OPTIONS="log_level=debug"
+ACTION=="add", SUBSYSTEM=="mem", KERNEL=="null", IMPORT{program}="/bin/sh -c 'printf \"TRUNCATED_OK=yes\nTRUNCATED_BAD=\"; i=0; while [ \"$i\" -lt 20000 ]; do printf A; i=$((i + 1)); done'"
+EOF
+
+udevadm control --reload
+SYSTEMD_LOG_LEVEL=debug udevadm trigger --verbose --settle --action add /dev/null
+
+udevadm info /dev/null | grep 'E: TRUNCATED_OK=yes' >/dev/null
+(! udevadm info /dev/null | grep 'E: TRUNCATED_BAD=' >/dev/null)
+
 rm /run/udev/rules.d/50-testsuite.rules
 udevadm control --reload