From ab41503c7c2f10316293db16eaf016e5b3cb32c3 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 27 May 2024 09:52:14 +0200 Subject: [PATCH] cnetlink: clone objects to ensure they are unchanged Libnl ops that support updating objects may modify the object, even if we haven't handled the notification yet, causing older stored notifications to use an object "from the future". Avoid this by cloning the new object. Both nl_object_clone() and nl_object_put() are NULL-safe, so we don't need to do any nullptr checks. Signed-off-by: Jonas Gorski --- src/netlink/cnetlink.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/netlink/cnetlink.cc b/src/netlink/cnetlink.cc index 4ce782c8..c295f510 100644 --- a/src/netlink/cnetlink.cc +++ b/src/netlink/cnetlink.cc @@ -925,8 +925,17 @@ void cnetlink::nl_cb_v2(struct nl_cache *cache, struct nl_object *old_obj, auto nl = static_cast(data); // only enqueue nl msgs if not in stopped state - if (nl->state != NL_STATE_STOPPED) - nl->nl_objs.emplace_back(action, old_obj, new_obj); + if (nl->state != NL_STATE_STOPPED) { + // If libnl updated the object instead of replacing it, old_obj will be a + // clone of the old object, and new_obj is the updated old object. Since + // later notifications may update the new_obj further, clone + // it to keep it in the state of the notification. + auto local_new = nl_object_clone(new_obj); + + nl->nl_objs.emplace_back(action, old_obj, local_new); + + nl_object_put(local_new); + } } void cnetlink::set_tapmanager(std::shared_ptr pm) {