Check for the last multipart message right as the first thing. The presumption probably was that the last message might still contain a payload we want to parse. However that cannot be true since that would have to be a type RTM_NEWNEIGH. This was not caught because older kernels were note sending NLMSG_DONE and probably relied on the fact that the parsing just stops after all the messages are walked through, which the NLMSG_OK macro successfully did. Resolves: https://issues.redhat.com/browse/RHEL-52449 Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> --- So technically this still has some issues, maybe. I could not find if our usage of libnl3 makes it easier for us so that we do not have to check for NLMSG_{ERROR,OVERRUN,NOOP} or whether these checks should be here as well. If yes, then we should add them. And we have (some of) these checks elsewhere in the code, so "maybe". Another thing is that we could avoid such errors by using nl_socket_set_cb(), calling nl_recvmsgs_default() and then parsing only the valid messages in a callback. On top of that we could have an abstraction on top this to utilise in all the netlink dumps we do, ditching our current abstraction which was a bit hard for me to go through, to be honest. And of course there might be other places in our codebase that expect the same behaviour as this code did and we should fix 'em all. After all the debugging for this piece I did not even check for those, maybe if this gets in I'll have a long think about it. src/util/virarptable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/virarptable.c b/src/util/virarptable.c index 8e805fb35332..604019c62a37 100644 --- a/src/util/virarptable.c +++ b/src/util/virarptable.c @@ -84,6 +84,9 @@ virArpTableGet(void) int len = nh->nlmsg_len; void *addr; + if (nh->nlmsg_type == NLMSG_DONE) + return table; + if (len < NLMSG_SPACE(sizeof(*r))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("wrong nlmsg len")); @@ -98,9 +101,6 @@ virArpTableGet(void) (!(r->ndm_state == NUD_STALE || r->ndm_state == NUD_REACHABLE))) continue; - if (nh->nlmsg_type == NLMSG_DONE) - return table; - VIR_WARNINGS_NO_CAST_ALIGN parse_rtattr(tb, NDA_MAX, NDA_RTA(r), NLMSG_PAYLOAD(nh, sizeof(*r))); VIR_WARNINGS_RESET -- 2.46.0