dmesg: detect wrapped msgbuf on the kernel side and if so, skip first line

Since 59f256ec35 dmesg(8) will always skip first line of the message
buffer, cause it might be incomplete.  The problem is that in most cases
it is complete, valid and contains the "---<<BOOT>>---" marker.  This
skip can be disabled with '-a', but that would also unhide all non-kernel
messages.  Move this functionality from dmesg(8) to kernel, since kernel
actually knows if wrap has happened or not.

The main motivation for the change is not actually the value of the
"---<<BOOT>>---" marker.  The problem breaks unit tests, that clear
message buffer, perform a test and then check the message buffer for
a result.  Example of such test is sys/kern/sonewconn_overflow.
This commit is contained in:
Gleb Smirnoff 2022-02-05 13:25:38 -08:00
parent 6598559fdf
commit c999e3481d
2 changed files with 20 additions and 7 deletions

View file

@ -184,10 +184,6 @@ main(int argc, char *argv[])
/* Strip leading \0's */
while (*p == '\0')
p++;
} else if (!all) {
/* Skip the first line, since it is probably incomplete. */
p = memchr(p, '\n', ep - p);
p++;
}
for (; p < ep; p = nextp) {
nextp = memchr(p, '\n', ep - p);

View file

@ -1058,9 +1058,10 @@ msgbufinit(void *ptr, int size)
static int
sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
{
char buf[128];
char buf[128], *bp;
u_int seq;
int error, len;
bool wrap;
error = priv_check(req->td, PRIV_MSGBUF);
if (error)
@ -1069,13 +1070,29 @@ sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
/* Read the whole buffer, one chunk at a time. */
mtx_lock(&msgbuf_lock);
msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
wrap = (seq != 0);
for (;;) {
len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
mtx_unlock(&msgbuf_lock);
if (len == 0)
return (SYSCTL_OUT(req, "", 1)); /* add nulterm */
error = sysctl_handle_opaque(oidp, buf, len, req);
if (wrap) {
/* Skip the first line, as it is probably incomplete. */
bp = memchr(buf, '\n', len);
if (bp == NULL) {
mtx_lock(&msgbuf_lock);
continue;
}
wrap = false;
bp++;
len -= bp - buf;
if (len == 0) {
mtx_lock(&msgbuf_lock);
continue;
}
} else
bp = buf;
error = sysctl_handle_opaque(oidp, bp, len, req);
if (error)
return (error);