diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2024-01-11 04:51:53 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2024-01-11 04:51:53 +0000 |
commit | e6f4c31460658697827aed7f29ec6e960d6f0a87 (patch) | |
tree | e7534d582581f988d0e395fd186ae5ec8eac0f7d | |
parent | 26caf57e0b0c02771b58ed99bc37b4810249d58e (diff) | |
download | src-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.c | 20 |
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; |