From: Brian Mak Date: Thu, 28 May 2026 19:08:04 +0000 (-0700) Subject: dmesg: fix off-by-one read buffer size X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=01a424f502cf87f4cbd1c88bb10714b9f87154d4;p=thirdparty%2Futil-linux.git dmesg: fix off-by-one read buffer size PRINTK_MESSAGE_MAX is 2048 in the kernel. In a formatted record that is exactly 2048 bytes, reading /proc/kmsg with a size of PRINTK_MESSAGE_MAX - 1 (2047) will result in the read syscall returning -EINVAL. We see such a case when using a large initrd, for which the kernel outputs loading spinner characters, based on the size of the initrd. For a large enough initrd, there will be enough spinner characters to create several formatted records of size 2048. We fix this by increasing the kmsg_buf size by 1, which increases the size used by the read syscall to PRINTK_MESSAGE_MAX (2048). Signed-off-by: Brian Mak --- diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c index 15a0d1e6b..e39ec34a8 100644 --- a/sys-utils/dmesg.c +++ b/sys-utils/dmesg.c @@ -75,6 +75,8 @@ #define DMESG_CALLER_PREFIX "caller=" #define DMESG_CALLER_PREFIXSZ (sizeof(DMESG_CALLER_PREFIX)-1) +#define PRINTK_MESSAGE_MAX 2048 + /* * Color scheme */ @@ -211,12 +213,14 @@ struct dmesg_control { int kmsg; /* /dev/kmsg file descriptor */ ssize_t kmsg_first_read;/* initial read() return code */ /* - * the kernel will give EINVAL if we do read() on /proc/kmsg with - * length insufficient for the next message. messages may be up to - * PRINTK_MESSAGE_MAX, which is defined as 2048, so we must be - * able to buffer at least that much in one call + * The kernel will give -EINVAL if we do read() on /proc/kmsg with + * length insufficient for the next message. Messages may be up to + * PRINTK_MESSAGE_MAX, which is defined as 2048, so the read() must + * use a size of at least that. We pass into read(), the size of + * kmsg_buf - 1. Therefore, kmsg_buf must have a size of at least + * PRINTK_MESSAGE_MAX + 1 bytes long. */ - char kmsg_buf[2048]; /* buffer to read kmsg data */ + char kmsg_buf[PRINTK_MESSAGE_MAX + 1]; /* kmsg data buffer */ usec_t since; /* filter records by time */ usec_t until; /* filter records by time */