On Fri, Mar 13, 2015 at 01:14:45AM +0000, Stuart Henderson wrote:
> While investigating a problem reported by Sevan Janiyan (where interface
> pppoe0 { passive } didn't get redisted) I ran into this reproducible
> crash.
>
> - start ospfd with a p2p interface (tried with pppoe and gif here).
> "passive" is required, e.g. interface gif0 { passive }
>
> - remove above p2p interface from config
>
> - ospfctl reload
>
> - *boom*
>
> Considering the address of tree, it would appear to be a use after free.
> (Hooray for kern.nosuidcoredump=3)
>
> (gdb) bt
> #0 0x00001e7559e24880 in lsa_tree_RB_FIND (head=0xdfdfdfdfdfdfdff7,
> elm=0x7f7ffffe5310) at /usr/src/usr.sbin/ospfd/rde_lsdb.c:39
> #1 0x00001e7559e25e63 in lsa_find_tree (tree=0xdfdfdfdfdfdfdff7, type=1,
> ls_id=1224736778, adv_rtr=1224736778)
> at /usr/src/usr.sbin/ospfd/rde_lsdb.c:526
> #2 0x00001e7559e25da9 in lsa_find (iface=0x1e77c1c00000, type=1 '\001',
> ls_id=1224736778, adv_rtr=1224736778)
> at /usr/src/usr.sbin/ospfd/rde_lsdb.c:505
> #3 0x00001e7559e2021f in rde_dispatch_imsg (fd=8, event=2,
> bula=0x1e7814ade000) at /usr/src/usr.sbin/ospfd/rde.c:421
> #4 0x00001e77681e81a8 in event_base_loop (base=0x1e77c1bff400,
> flags=Variable "flags" is not available.
> )
> at /usr/src/lib/libevent/event.c:350
> #5 0x00001e7559e1f862 in rde (xconf=0x1e77833ec800,
> pipe_parent2rde=0x1e755a2358a8, pipe_ospfe2rde=0x1e755a2358b8,
> pipe_parent2ospfe=0x1e755a2358a0) at /usr/src/usr.sbin/ospfd/rde.c:186
> #6 0x00001e7559e1507e in main (argc=0, argv=0x7f7ffffe5b18)
> at /usr/src/usr.sbin/ospfd/ospfd.c:242
>
Can you try the following diff. Not sure if it is right but it seems to
solve the crash for me.
--
:wq Claudio
Index: ospfd.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.c,v
retrieving revision 1.83
diff -u -p -r1.83 ospfd.c
--- ospfd.c 10 Feb 2015 05:24:48 -0000 1.83
+++ ospfd.c 13 Mar 2015 08:13:00 -0000
@@ -821,6 +821,8 @@ merge_interfaces(struct area *a, struct
i->name);
if (ospfd_process == PROC_OSPF_ENGINE)
if_fsm(i, IF_EVT_DOWN);
+ else if (ospfd_process == PROC_RDE_ENGINE)
+ rde_nbr_iface_del(i);
LIST_REMOVE(i, entry);
if_del(i);
}
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/rde.c,v
retrieving revision 1.96
diff -u -p -r1.96 rde.c
--- rde.c 12 Jul 2014 20:16:38 -0000 1.96
+++ rde.c 13 Mar 2015 08:10:42 -0000
@@ -963,6 +963,22 @@ rde_nbr_new(u_int32_t peerid, struct rde
}
void
+rde_nbr_iface_del(struct iface *iface)
+{
+ struct rde_nbr_head *head;
+ struct rde_nbr *nbr, *xnbr;
+ u_int32_t i;
+
+ for (i = 0; i <= rdenbrtable.hashmask; i++) {
+ head = &rdenbrtable.hashtbl[i];
+ LIST_FOREACH_SAFE(nbr, head, hash, xnbr) {
+ if (nbr->iface == iface)
+ rde_nbr_del(nbr);
+ }
+ }
+}
+
+void
rde_nbr_del(struct rde_nbr *nbr)
{
if (nbr == NULL)
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/rde.h,v
retrieving revision 1.38
diff -u -p -r1.38 rde.h
--- rde.h 9 May 2011 12:24:41 -0000 1.38
+++ rde.h 13 Mar 2015 08:11:15 -0000
@@ -118,6 +118,7 @@ u_int32_t rde_router_id(void);
struct area *rde_backbone_area(void);
void rde_send_change_kroute(struct rt_node *);
void rde_send_delete_kroute(struct rt_node *);
+void rde_nbr_iface_del(struct iface *);
void rde_nbr_del(struct rde_nbr *);
int rde_nbr_loading(struct area *);
struct rde_nbr *rde_nbr_self(struct area *);