]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: Prevent use after free
authorDonald Sharp <sharpd@nvidia.com>
Thu, 4 Nov 2021 17:00:51 +0000 (13:00 -0400)
committerDonald Sharp <sharpd@nvidia.com>
Fri, 5 Nov 2021 22:00:07 +0000 (18:00 -0400)
I am seeing a crash of ospf6d with this stack trace:

OSPF6: Received signal 11 at 1636042827 (si_addr 0x0, PC 0x55efc2d09ec2); aborting...
OSPF6: zlog_signal+0x18c                  7fe20c8ca19a     7ffd08035590 /lib/libfrr.so.0 (mapped at 0x7fe20c819000)
OSPF6: core_handler+0xe3                  7fe20c90805e     7ffd080356b0 /lib/libfrr.so.0 (mapped at 0x7fe20c819000)
OSPF6: funlockfile+0x50                   7fe20c7f8140     7ffd08035800 /lib/x86_64-linux-gnu/libpthread.so.0 (mapped at 0x7fe20c7e4000)
OSPF6:     ---- signal ----
OSPF6: ospf6_neighbor_state_change+0xdc     55efc2d09ec2     7ffd08035d90 /usr/lib/frr/ospf6d (mapped at 0x55efc2c8e000)
OSPF6: exchange_done+0x15c                55efc2d0ab4a     7ffd08035dc0 /usr/lib/frr/ospf6d (mapped at 0x55efc2c8e000)
OSPF6: thread_call+0xc2                   7fe20c91ee32     7ffd08035df0 /lib/libfrr.so.0 (mapped at 0x7fe20c819000)
OSPF6: frr_run+0x217                      7fe20c8bf7f3     7ffd08035eb0 /lib/libfrr.so.0 (mapped at 0x7fe20c819000)
OSPF6: main+0xf3                          55efc2cd7573     7ffd08035fc0 /usr/lib/frr/ospf6d (mapped at 0x55efc2c8e000)
OSPF6: __libc_start_main+0xea             7fe20c645d0a     7ffd08036000 /lib/x86_64-linux-gnu/libc.so.6 (mapped at 0x7fe20c61f000)
OSPF6: _start+0x2a                        55efc2cd706a     7ffd080360d0 /usr/lib/frr/ospf6d (mapped at 0x55efc2c8e000)
OSPF6: in thread exchange_done scheduled from ospf6d/ospf6_message.c:2264 ospf6_dbdesc_send_newone()

The stack trace when decoded is:

(gdb) l *(ospf6_neighbor_state_change+0xdc)
0x7bec2 is in ospf6_neighbor_state_change (ospf6d/ospf6_neighbor.c:200).
warning: Source file is more recent than executable.
195    on->name, ospf6_neighbor_state_str[prev_state],
196    ospf6_neighbor_state_str[next_state],
197    ospf6_neighbor_event_string(event));
198 }
199
200 /* Optionally notify about adjacency changes */
201 if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
202        OSPF6_LOG_ADJACENCY_CHANGES)
203     && (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
204    OSPF6_LOG_ADJACENCY_DETAIL)

OSPFv3 is creating the event without a managing thread and as such
if the event is not run before a deletion event comes in memory
will be freed up and we'll start trying to access memory we should
not.  Modify ospfv3 to track the thread and appropriately stop
it when the memory is deleted or it is no longer need to run
that bit of code.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
ospf6d/ospf6_message.c
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_neighbor.h

index a81c3e728f5bb6e30fca297c1969dc83f79ba840..49a379aa17c87ab423993316a3e503c3a0057479 100644 (file)
@@ -772,7 +772,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
        /* More bit check */
        if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MBIT)
            && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
-               thread_add_event(master, exchange_done, on, 0, NULL);
+               thread_add_event(master, exchange_done, on, 0,
+                                &on->thread_exchange_done);
        else {
                thread_add_event(master, ospf6_dbdesc_send_newone, on, 0,
                                 &on->thread_send_dbdesc);
@@ -2261,7 +2262,8 @@ int ospf6_dbdesc_send_newone(struct thread *thread)
        if (!CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
            !CHECK_FLAG(on->dbdesc_last.bits, OSPF6_DBDESC_MBIT)
            && !CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT))
-               thread_add_event(master, exchange_done, on, 0, NULL);
+               thread_add_event(master, exchange_done, on, 0,
+                                &on->thread_exchange_done);
 
        thread_execute(master, ospf6_dbdesc_send, on, 0);
        return 0;
index 36948dc0a7cfbeca5504e75a7039904e508ddfc6..1ff986d278132049f4e58e536091aaa36d025ece 100644 (file)
@@ -168,6 +168,7 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on)
        THREAD_OFF(on->thread_send_lsreq);
        THREAD_OFF(on->thread_send_lsupdate);
        THREAD_OFF(on->thread_send_lsack);
+       THREAD_OFF(on->thread_exchange_done);
        THREAD_OFF(on->gr_helper_info.t_grace_timer);
 
        bfd_sess_free(&on->bfd_session);
@@ -603,6 +604,7 @@ int oneway_received(struct thread *thread)
        THREAD_OFF(on->thread_send_lsreq);
        THREAD_OFF(on->thread_send_lsupdate);
        THREAD_OFF(on->thread_send_lsack);
+       THREAD_OFF(on->thread_exchange_done);
 
        return 0;
 }
index f7735b87b9b3cdcd770c580518c656715e870ca2..376d2fe4bc1400f5139363b3d70ee6adbaaa9571 100644 (file)
@@ -136,6 +136,7 @@ struct ospf6_neighbor {
        struct thread *thread_send_lsreq;
        struct thread *thread_send_lsupdate;
        struct thread *thread_send_lsack;
+       struct thread *thread_exchange_done;
 
        /* BFD information */
        struct bfd_session_params *bfd_session;