summaryrefslogtreecommitdiff
path: root/src/libsystemd
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-11-26 09:35:53 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-11-26 11:28:27 +0900
commita8ac052624495d5f974674187e29c6fb9671f94f (patch)
treeee232209b9c6757dc308dc7755ef374221445bfc /src/libsystemd
parent9482429af9696ce16b90b2de97b15336235bcd30 (diff)
downloadsystemd-a8ac052624495d5f974674187e29c6fb9671f94f.tar.gz
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.
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 1aaa4b712c..2a9f641419 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -376,10 +376,9 @@ finalize:
* On failure, a negative error code is returned.
*/
int socket_read_message(sd_netlink *nl) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
- bool multi_part = false, done = false;
- size_t len;
+ bool done = false;
uint32_t group;
+ size_t len;
int r;
assert(nl);
@@ -405,12 +404,7 @@ int socket_read_message(sd_netlink *nl) {
return 0;
}
- if (nl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
- 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)) {
+ for (struct nlmsghdr *hdr = nl->rbuffer; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
r = parse_message_one(nl, group, hdr, &m);
@@ -419,36 +413,44 @@ int socket_read_message(sd_netlink *nl) {
if (r == 0)
continue;
- if (hdr->nlmsg_type == NLMSG_DONE) {
- /* finished reading multi-part message */
- done = true;
+ if (hdr->nlmsg_flags & NLM_F_MULTI) {
+ if (hdr->nlmsg_type == NLMSG_DONE) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *existing = NULL;
- /* if first is not defined, put NLMSG_DONE into the receive queue. */
- if (first)
- continue;
- }
+ /* finished reading multi-part message */
+ existing = hashmap_remove(nl->rqueue_partial_by_serial, UINT32_TO_PTR(hdr->nlmsg_seq));
- /* push the message onto the multi-part message stack */
- if (first)
- m->next = first;
- first = TAKE_PTR(m);
+ /* 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;
+ }
+
+ } else {
+ r = netlink_queue_received_message(nl, m);
+ if (r < 0)
+ return r;
+
+ done = true;
+ }
}
if (len > 0)
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;
}