tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

possible bug when deleting a route during if_detach

if_detach() calls rt_walktree with if_rt_walktree as the visiting callback,
which calls rtrequest(RTM_DELETE, ...) from within the tree iteration in
rn_walktree. Although rn_walktree protects itself from deletion of the current
node while iterating, there is no protection if the *next* node is deleted
during the callback. This can happen if the called node is a route and there is
a clone of it following it in the iteration sequence. That is because
rtrequest1, in the RTM_DELETE case, will call rtflushclone, and this will
delete the cloned route. Upon return to rn_walktree, the next node may be
deleted, but rn_walktree will dereference it.

Here's the call sequence:
  +-rn_walktree /* rt2 is next */
  | `-rn_walktree_visitor(rt1)
  |   `-if_rt_detach(rt1)
  |     `-rtrequest1(rt1)
  |       +-rtflushclone(rt1)
  |       | `-rt_walktree(rt1)
  |       |   `-rn_walktree_visitor(rt2)
  |       |     `-rtflushclone1(rt2)
  |       |       `-rtdeletemsg(rt2)
  |       |         `-rtfree(rt2)
  |       `-rtfree(rt1)
  `- /* crash on deref of rt2 (next) */

The cloned route in this case (labeled rt2 above) was created as a consequence
of if_arp.c setting the RTF_CLONING flag, presumably on rt1, but I haven't dug
into how route.c and radix.c determine their ordering yet to satisfy myself
that  this is the case.

It seems the fundamental problem is that rn_walktree is defenseless against
this kind of radix tree mutation while it is iterating. Am I right, or is my
system somehow abusing some assumption about how those radix trees are supposed
to be ordered?

Home | Main Index | Thread Index | Old Index