aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2022-02-05 21:25:38 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2022-02-05 21:35:31 +0000
commitc999e3481d936980354d09e3d6a138e5dde5fabc (patch)
treec7defc12c617ab0487123aa6922fada00acaec66
parent6598559fdf0c6342b6c30229430c739c42dc9941 (diff)
downloadsrc-c999e3481d936980354d09e3d6a138e5dde5fabc.tar.gz
src-c999e3481d936980354d09e3d6a138e5dde5fabc.zip
dmesg: detect wrapped msgbuf on the kernel side and if so, skip first line
Since 59f256ec35d3 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.
-rw-r--r--sbin/dmesg/dmesg.c4
-rw-r--r--sys/kern/subr_prf.c23
2 files changed, 20 insertions, 7 deletions
diff --git a/sbin/dmesg/dmesg.c b/sbin/dmesg/dmesg.c
index 469582204f7b..f266e6b98b39 100644
--- a/sbin/dmesg/dmesg.c
+++ b/sbin/dmesg/dmesg.c
@@ -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);
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index 1106587ebbe7..62a0bd0a3699 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -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);