pimd: fix multicast boundary list lifetime and ACL evaluation - #22122
Conversation
Jafaral
commented
May 30, 2026
- Fix dangling boundary list pointers by storing names and looking them up at use time
- Preserve ACL first-match order for mixed cisco/standard entries
- Clean up duplicate IGMPv3 debug output
- Add topotest coverage for list deletion and mixed ACL ordering
Greptile SummaryThis PR fixes a use-after-free hazard in pimd where
Confidence Score: 5/5Safe to merge; the changes are well-scoped, all boundary field consumers are updated consistently, and the new test covers both the crash-safety and the ordering correctness goals. All seven changed files are internally consistent: the type change in pim_iface.h is reflected everywhere the fields are read or written, memory management follows the established XSTRDUP/XFREE pattern used by sibling fields, and the refactored pim_access_list_apply is logically equivalent to filter_match_zebra in lib/filter.c. No call sites were overlooked. No files require special attention; pimd/pim_util.c carries the most logic change but the single-pass rewrite is straightforward and correct. Important Files Changed
Sequence DiagramsequenceDiagram
participant Admin
participant NB as NB Config (pim_nb_config.c)
participant Iface as pim_interface
participant Util as pim_is_group_filtered
Note over Admin,Util: Old behavior - dangling pointer on list deletion
Admin->>NB: ip multicast boundary pim-acl
NB->>Iface: "boundary_acl = access_list_lookup(pim-acl)"
Admin->>Admin: no access-list pim-acl (list freed)
Util->>Iface: "read boundary_acl <- dangling pointer / crash"
Note over Admin,Util: New behavior - name stored, lazy lookup
Admin->>NB: ip multicast boundary pim-acl
NB->>Iface: "boundary_acl = XSTRDUP(pim-acl)"
Admin->>Admin: no access-list pim-acl (list freed, name string intact)
Util->>Util: "acl = access_list_lookup(boundary_acl)"
alt ACL still exists
Util->>Util: apply ACL filter
else ACL deleted
Util->>Util: skip filtering (pass traffic)
end
Reviews (2): Last reviewed commit: "tests: cover boundary list deletion and ..." | Re-trigger Greptile |
f88d51a to
5c00f9b
Compare
|
@greptile review |
|
|
||
| XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->nbr_plist); | ||
| XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->allow_rp_plist); | ||
| XFREE(MTYPE_PIM_PLIST_NAME, pim_ifp->boundary_oil_plist); |
There was a problem hiding this comment.
Why are we not hooked into pim_prefix_list_update for prefix list changes for the interfaces prefix lists? Looking up the prefix list when an operator can have 10's of thousands of them does not seem efficient or correct. Every other place I am aware of stores both the name and the pointer. When the prefix list is changed we get the callback into pim_prefix_list_update which should update the plist pointer as needed.
| return true; | ||
| } else if (group_addr == cfilter->addr.s_addr) | ||
| return true; | ||
| } else { |
There was a problem hiding this comment.
This seems like a separate bug fix of some sort here, that is not related to what the commit comment talks about at all.
There was a problem hiding this comment.
Correct, this bug is separate but got exposed by my other fixes. Will split it in its own commit.
| { | ||
| const struct filter_zebra *zfilter = &filter->u.zfilter; | ||
|
|
||
| if (zfilter->prefix.family != p->family) |
There was a problem hiding this comment.
Why wouldn't this check actually belong in prefix_match? It seems like an odd thing to not be checking in that function?
There was a problem hiding this comment.
We can add it to prefix_match. However most users ofΒ prefix_matchΒ use it in a same-family context and don't need the extra check. There are a few places that add a family check explicitly. It is good to refactor those and add a common function prefix_match_with_familiy to expose the new behavior in the library. I will do that in a separate PR to avoid polluting this bug fix PR.
ddfa9e7 to
921444c
Compare
Store prefix-list and access-list names on each interface together with cached pointers. Refresh or clear the pointers from pim_prefix_list_update() and pim_access_list_update() when lists change or are deleted, consistent with other pimd plist/ACL usage. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
The record type was already printed in the message prefix, so remove the redundant type=%d field from the per-record debug line. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
Use addr/addr_mask for classic cisco entries instead of wtf.mask_mask. This bug was latent since the ACL helper moved to pim_util.c; the old access_list_apply fallback masked it until single-pass evaluation. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
Evaluate cisco and standard access-list entries in a single pass so mixed ACLs honor first-match semantics for both MSDP and multicast boundary filtering. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
Extend pim_boundary_acl to verify pimd survives deleting a prefix-list or access-list while boundary config remains, and that a standard permit entry before a cisco deny is evaluated in first-match order. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
|
@Mergifyio backport stable/10.6 stable/10.5 |
β Backports have been createdDetails
Cherry-pick of 8db6c18 has failed: Cherry-pick of d4e324c has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally
Cherry-pick of 8db6c18 has failed: Cherry-pick of d4e324c has failed: Cherry-pick of 0d5338e has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally |
pimd: fix multicast boundary list lifetime and ACL evaluation (backport #22122)