aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2024-01-11 04:51:53 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2024-01-11 04:51:53 +0000
commite6f4c31460658697827aed7f29ec6e960d6f0a87 (patch)
treee7534d582581f988d0e395fd186ae5ec8eac0f7d
parent26caf57e0b0c02771b58ed99bc37b4810249d58e (diff)
downloadsrc-e6f4c31460658697827aed7f29ec6e960d6f0a87.tar.gz
src-e6f4c31460658697827aed7f29ec6e960d6f0a87.zip
netlink: improve edge case when reading out truncated last nlmsg in nb
When there is not enough space for one full message we return it truncated. This enters special block of code that previously may leave empty buffer with offset == datalen in the queue. Avoid that, as dealing later with empty buffers causes more pain than just avoiding them. While here add missing msgrcv increment.
-rw-r--r--sys/netlink/netlink_domain.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
index 4790845d1d31..94989af73dfe 100644
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -762,11 +762,23 @@ nl_soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio,
} else if (len == 0 && uio->uio_resid > 0) {
flags |= MSG_TRUNC;
partlen = uio->uio_resid;
- if (!peek) {
- /* XXX: may leave empty nb */
+ if (peek)
+ goto nospace;
+ datalen += hdr->nlmsg_len;
+ if (nb->offset + hdr->nlmsg_len ==
+ nb->datalen) {
+ /*
+ * Avoid leaving empty nb.
+ * Process last nb normally.
+ * Trust uiomove() to care
+ * about negative uio_resid.
+ */
+ nb = TAILQ_NEXT(nb, tailq);
+ overflow = 0;
+ partlen = 0;
+ } else
nb->offset += hdr->nlmsg_len;
- datalen += hdr->nlmsg_len;
- }
+ msgrcv++;
} else
partlen = 0;
goto nospace;