diff options
author | Donald Sharp <sharpd@nvidia.com> | 2021-11-05 22:56:42 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@nvidia.com> | 2021-11-05 23:00:10 +0100 |
commit | 81e06dd3c328517872ca705789d37e599720d43f (patch) | |
tree | 6772460fb1509e6177494196d0e3ed00df0094ba /ospf6d | |
parent | ospf6d: Prevent use after free (diff) | |
download | frr-81e06dd3c328517872ca705789d37e599720d43f.tar.xz frr-81e06dd3c328517872ca705789d37e599720d43f.zip |
ospf6d: Prevent crash in adj_ok
The adj_ok thread event is being added but not killed
when the underlying interface is deleted. I am seeing
this crash:
OSPF6: Received signal 11 at 1636142186 (si_addr 0x0, PC 0x561d7fc42285); aborting...
OSPF6: zlog_signal+0x18c 7f227e93519a 7ffdae024590 /lib/libfrr.so.0 (mapped at 0x7f227e884000)
OSPF6: core_handler+0xe3 7f227e97305e 7ffdae0246b0 /lib/libfrr.so.0 (mapped at 0x7f227e884000)
OSPF6: funlockfile+0x50 7f227e863140 7ffdae024800 /lib/x86_64-linux-gnu/libpthread.so.0 (mapped at 0x7f227e84f000)
OSPF6: ---- signal ----
OSPF6: need_adjacency+0x10 561d7fc42285 7ffdae024db0 /usr/lib/frr/ospf6d (mapped at 0x561d7fbc6000)
OSPF6: adj_ok+0x180 561d7fc42f0b 7ffdae024dc0 /usr/lib/frr/ospf6d (mapped at 0x561d7fbc6000)
OSPF6: thread_call+0xc2 7f227e989e32 7ffdae024e00 /lib/libfrr.so.0 (mapped at 0x7f227e884000)
OSPF6: frr_run+0x217 7f227e92a7f3 7ffdae024ec0 /lib/libfrr.so.0 (mapped at 0x7f227e884000)
OSPF6: main+0xf3 561d7fc0f573 7ffdae024fd0 /usr/lib/frr/ospf6d (mapped at 0x561d7fbc6000)
OSPF6: __libc_start_main+0xea 7f227e6b0d0a 7ffdae025010 /lib/x86_64-linux-gnu/libc.so.6 (mapped at 0x7f227e68a000)
OSPF6: _start+0x2a 561d7fc0f06a 7ffdae0250e0 /usr/lib/frr/ospf6d (mapped at 0x561d7fbc6000)
OSPF6: in thread adj_ok scheduled from ospf6d/ospf6_interface.c:678 dr_election()
The crash is in the on->ospf6_if pointer is NULL. The only way this could
happen from what I can tell is that the event is added to the system
and then we immediately delete the interface, removing the memory
but not freeing up the adj_ok thread event.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Diffstat (limited to 'ospf6d')
-rw-r--r-- | ospf6d/ospf6_interface.c | 3 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.c | 3 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.h | 1 |
3 files changed, 6 insertions, 1 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 64992bbce..4205be38b 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -675,7 +675,8 @@ uint8_t dr_election(struct ospf6_interface *oi) if (on->state < OSPF6_NEIGHBOR_TWOWAY) continue; /* Schedule AdjOK. */ - thread_add_event(master, adj_ok, on, 0, NULL); + thread_add_event(master, adj_ok, on, 0, + &on->thread_adj_ok); } } diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 1ff986d27..3d0dde8c6 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -169,6 +169,8 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on) THREAD_OFF(on->thread_send_lsupdate); THREAD_OFF(on->thread_send_lsack); THREAD_OFF(on->thread_exchange_done); + THREAD_OFF(on->thread_adj_ok); + THREAD_OFF(on->gr_helper_info.t_grace_timer); bfd_sess_free(&on->bfd_session); @@ -605,6 +607,7 @@ int oneway_received(struct thread *thread) THREAD_OFF(on->thread_send_lsupdate); THREAD_OFF(on->thread_send_lsack); THREAD_OFF(on->thread_exchange_done); + THREAD_OFF(on->thread_adj_ok); return 0; } diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index 376d2fe4b..de59a1ccf 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -137,6 +137,7 @@ struct ospf6_neighbor { struct thread *thread_send_lsupdate; struct thread *thread_send_lsack; struct thread *thread_exchange_done; + struct thread *thread_adj_ok; /* BFD information */ struct bfd_session_params *bfd_session; |