1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

sd-netlink: do not link non-multipart messages

Previously, if a single packet contains multiple non-multipart messages,
then the messages were linked and saved as a single entry, especially
even if the messages has different serial numbers. Though, not sure if
the kernel sends such packet. But at least for safety, let's link only
multipart messages.
This commit is contained in:
Yu Watanabe 2022-11-26 09:35:53 +09:00
parent 9482429af9
commit a8ac052624

View File

@ -376,10 +376,9 @@ finalize:
* On failure, a negative error code is returned. * On failure, a negative error code is returned.
*/ */
int socket_read_message(sd_netlink *nl) { int socket_read_message(sd_netlink *nl) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL; bool done = false;
bool multi_part = false, done = false;
size_t len;
uint32_t group; uint32_t group;
size_t len;
int r; int r;
assert(nl); assert(nl);
@ -405,12 +404,7 @@ int socket_read_message(sd_netlink *nl) {
return 0; return 0;
} }
if (nl->rbuffer->nlmsg_flags & NLM_F_MULTI) { for (struct nlmsghdr *hdr = nl->rbuffer; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
multi_part = true;
first = hashmap_remove(nl->rqueue_partial_by_serial, UINT32_TO_PTR(nl->rbuffer->nlmsg_seq));
}
for (struct nlmsghdr *hdr = nl->rbuffer; NLMSG_OK(hdr, len) && !done; hdr = NLMSG_NEXT(hdr, len)) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
r = parse_message_one(nl, group, hdr, &m); r = parse_message_one(nl, group, hdr, &m);
@ -419,36 +413,44 @@ int socket_read_message(sd_netlink *nl) {
if (r == 0) if (r == 0)
continue; continue;
if (hdr->nlmsg_flags & NLM_F_MULTI) {
if (hdr->nlmsg_type == NLMSG_DONE) { if (hdr->nlmsg_type == NLMSG_DONE) {
/* finished reading multi-part message */ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *existing = NULL;
done = true;
/* if first is not defined, put NLMSG_DONE into the receive queue. */ /* finished reading multi-part message */
if (first) existing = hashmap_remove(nl->rqueue_partial_by_serial, UINT32_TO_PTR(hdr->nlmsg_seq));
continue;
/* if we receive only NLMSG_DONE, put it into the receive queue. */
r = netlink_queue_received_message(nl, existing ?: m);
if (r < 0)
return r;
done = true;
} else {
sd_netlink_message *existing;
existing = hashmap_remove(nl->rqueue_partial_by_serial, UINT32_TO_PTR(hdr->nlmsg_seq));
if (existing)
/* push the message onto the multi-part message stack */
m->next = existing;
/* put it into the queue for partially received messages. */
r = netlink_queue_partially_received_message(nl, m);
if (r < 0)
return r;
} }
/* push the message onto the multi-part message stack */ } else {
if (first) r = netlink_queue_received_message(nl, m);
m->next = first; if (r < 0)
first = TAKE_PTR(m); return r;
done = true;
}
} }
if (len > 0) if (len > 0)
log_debug("sd-netlink: discarding trailing %zu bytes of incoming message", len); log_debug("sd-netlink: discarding trailing %zu bytes of incoming message", len);
if (!first)
return 0;
done = done || !multi_part;
if (done)
/* we got a complete message, push it on the read queue */
r = netlink_queue_received_message(nl, first);
else
/* we only got a partial multi-part message, push it on the partial read queue. */
r = netlink_queue_partially_received_message(nl, first);
if (r < 0)
return r;
return done; return done;
} }