diff options
| author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-05-01 22:14:00 -0300 |
|---|---|---|
| committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2020-06-05 14:36:54 -0300 |
| commit | 81b504228564980bf4dcc7ad4808e2833012c35e (patch) | |
| tree | 3202d8c4803bba8d2fe5fed4ca4ac1f00370d1b2 /lib/plist.c | |
| parent | 88b8bfdc8af8e9ea45d8b7149efd9fcc8fc2e95f (diff) | |
lib: fix route map crash on prefix list removal
Changes:
- Refactor list entry deletion to use a function that properly notifies
route map on deletion (fixes a heap-use-after-free).
- Prefix list entry wild card sets `le` to maximum IP mask value and
`any` is a boolean.
- Fix prefix list trie removal order (in `prefix_list_entry_update_start`).
- Let only the `any` callback change the value of field `any`.
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'lib/plist.c')
| -rw-r--r-- | lib/plist.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/lib/plist.c b/lib/plist.c index 958d98dc96..981e86e2ac 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -661,6 +661,8 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple) if (!ple->installed) return; + prefix_list_trie_del(pl, ple); + /* List manipulation: shameless copy from `prefix_list_entry_delete`. */ if (ple->prev) ple->prev->next = ple->next; @@ -671,11 +673,17 @@ void prefix_list_entry_update_start(struct prefix_list_entry *ple) else pl->tail = ple->prev; - prefix_list_trie_del(pl, ple); route_map_notify_pentry_dependencies(pl->name, ple, RMAP_EVENT_PLIST_DELETED); pl->count--; + route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_DELETED); + if (pl->master->delete_hook) + (*pl->master->delete_hook)(pl); + + if (pl->head || pl->tail || pl->desc) + pl->master->recent = pl; + ple->installed = false; } @@ -695,6 +703,14 @@ void prefix_list_entry_update_finish(struct prefix_list_entry *ple) if (ple->installed) return; + /* + * Check if the entry is installable: + * We can only install entry if at least the prefix is provided (IPv4 + * or IPv6). + */ + if (ple->prefix.family != AF_INET && ple->prefix.family != AF_INET6) + return; + /* List manipulation: shameless copy from `prefix_list_entry_add`. */ if (pl->tail && ple->seq > pl->tail->seq) point = NULL; @@ -742,6 +758,21 @@ void prefix_list_entry_update_finish(struct prefix_list_entry *ple) ple->installed = true; } +/** + * Same as `prefix_list_entry_delete` but without `free()`ing the list if its + * empty. + * + * \param[in] ple prefix list entry. + */ +void prefix_list_entry_delete2(struct prefix_list_entry *ple) +{ + /* Does the boiler plate list removal and entry removal notification. */ + prefix_list_entry_update_start(ple); + + /* Effective `free()` memory. */ + prefix_list_entry_free(ple); +} + /* Return string of prefix_list_type. */ static const char *prefix_list_type_str(struct prefix_list_entry *pentry) { |
