From d9b1f6fbf9935a9d54c78987a04af7cda3740c56 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Wed, 10 Jan 2024 20:51:53 -0800 Subject: [PATCH] netlink: fix bug with socket buffer character counter underflow Cover case when an nb that we are now reading in full had been partially read by previous read(2) and now has positive offset. Throw couple assertions that helped to catch that earlier. --- sys/netlink/netlink_domain.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c index 7ecafbf99d26..777aff43000a 100644 --- a/sys/netlink/netlink_domain.c +++ b/sys/netlink/netlink_domain.c @@ -744,6 +744,7 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, offset = nb->offset; while (offset < nb->datalen) { hdr = (struct nlmsghdr *)&nb->data[offset]; + MPASS(nb->offset + hdr->nlmsg_len <= nb->datalen); if (uio->uio_resid < len + hdr->nlmsg_len) { overflow = len + hdr->nlmsg_len - uio->uio_resid; @@ -784,7 +785,7 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, msgrcv++; } MPASS(offset == nb->datalen); - datalen += nb->datalen; + datalen += nb->datalen - nb->offset; } nospace: last = nb; @@ -796,6 +797,7 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, TAILQ_FIRST(&sb->nl_queue) = last; last->tailq.tqe_prev = &TAILQ_FIRST(&sb->nl_queue); } + MPASS(sb->sb_acc >= datalen); sb->sb_acc -= datalen; sb->sb_ccc -= datalen; }