From c24694a8e93dcc17ee7837a42d609f0eea042fd3 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 28 Jul 2026 13:53:11 +0200 Subject: [PATCH] drivers/syslog: fix syslog_write() returning -EIO on every write syslog_write_foreach() compares an unsigned count against a signed accumulator: size_t nwritten = 0; ssize_t nwritten_max = -EIO; ... if (nwritten > nwritten_max) { nwritten_max = nwritten; } return nwritten_max; The usual arithmetic conversions promote nwritten_max to size_t, so -EIO becomes 4294967291 on a 32-bit target, and the comparison is never true. nwritten_max keeps its initial value and the function returns -EIO no matter how many bytes actually went out. Observed under gdb on a running target: nwritten == 64, nwritten_max == -5, (nwritten > nwritten_max) == 0. Most callers discard the result -- syslog() itself returns void -- so this is normally invisible. It becomes fatal when /dev/console is backed by syslog_console_write(), because then stdio acts on it. lib_fflush_unlocked() sees a negative return, sets __FS_FLAG_ERROR and returns early, before resetting fs_bufpos. The bytes have already been emitted, but the buffer is never cleared, so every subsequent stdio call re-flushes the same CONFIG_STDIO_BUFFER_SIZE bytes. The console fills with one repeated fragment and the system makes no further progress. Reaching that state needs CONFIG_CONSOLE_SYSLOG=y together with no driver claiming /dev/console ahead of syslog_console_init(). Three in-tree defconfigs qualify: x86/qemu-i486:ostest, renesas/skp16c26:ostest and x86_64/qemu-intel64:earlyfb. The other 56 CONSOLE_SYSLOG configurations have a serial console that registers /dev/console first, which is why this has gone unnoticed. Introduced by 1685e8ff7b ("syslog: avoid an infinite loop if one channel fails"), which changed nwritten_max from size_t to ssize_t = -EIO so that an all-channels-failed case could be reported. Give nwritten the same type so the comparison is signed, which preserves that intent: nwritten_max stays -EIO only when no channel wrote anything. nwritten is never negative, so the remaining comparisons against buflen are unaffected. Signed-off-by: Marco Casaroli Assisted-by: Claude Opus 5 (1M context) --- drivers/syslog/syslog_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/syslog/syslog_write.c b/drivers/syslog/syslog_write.c index 94e6c0d330e..51ac92d6363 100644 --- a/drivers/syslog/syslog_write.c +++ b/drivers/syslog/syslog_write.c @@ -106,7 +106,7 @@ ssize_t syslog_write_foreach(FAR const char *buffer, { syslog_write_t write; syslog_putc_t putc; - size_t nwritten = 0; + ssize_t nwritten = 0; ssize_t nwritten_max = -EIO; ssize_t ret; int i;