]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Table export: fixed inconsistency in export_rejected_map
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Tue, 25 Feb 2025 11:46:06 +0000 (12:46 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 25 Feb 2025 13:53:10 +0000 (14:53 +0100)
When updates arrived in such an order that the first one was rejected and
the second one got accepted, the export_rejected_map flag mistakenly
stayed set, leaking the route ID.

In the RA_OPTIMAL channel mode, there are consistency checks that at
most one route for a net has been accepted or rejected. After some time,
the leaked ID and bit in export_rejected_map caused spurious crashes in
asserts later in channel_notify_basic().

Thanks to NIX-CZ and Maiyun Zhang for reporting this.

nest/rt-table.c

index 3ce2e21000bf8efba00acc472adb7926f8e9fd39..d1ffd40213d069ac2b253712d1b94be9019bf068 100644 (file)
@@ -1197,8 +1197,18 @@ rt_notify_basic(struct channel *c, const rte *new, const rte *old)
   }
 
   /* Have we exported the old route? */
-  if (old && !bmap_test(&c->export_accepted_map, old->id))
-    old = NULL;
+  if (old)
+    /* If the old route exists, it is either in rejected or in accepted map.
+     * If it is in rejcted map, we clear it right now, if it is in accepted map,
+     * we get rid of it in do_rt_notify. */
+    if (bmap_test(&c->export_rejected_map, old->id))
+    {
+      ASSERT_DIE(!bmap_test(&c->export_accepted_map, old->id));
+      bmap_clear(&c->export_rejected_map, old->id);
+      old = NULL;
+    }
+    else
+      ASSERT_DIE(bmap_test(&c->export_accepted_map, old->id));
 
   /* Withdraw to withdraw. */
   if (!np && !old)