GPF when doing jail -r, possibly an use-after-free

Bjoern A. Zeeb bzeeb-lists at
Sun Jul 8 20:53:00 UTC 2012

On 8. Jul 2012, at 20:40 , Mikolaj Golub wrote:

> On Sat, 7 Jul 2012 20:38:23 +0000 Bjoern A. Zeeb wrote:
> BAZ> On 6. Jul 2012, at 05:53 , Mikolaj Golub wrote:
>>> On Thu, 5 Jul 2012 20:21:53 +0000 Bjoern A. Zeeb wrote:
>>> BAZ> On 5. Jul 2012, at 19:53 , Mikolaj Golub wrote:
>>>>> On Thu, 05 Jul 2012 12:18:20 -0700 Xin Li wrote:
>>>>> XL> Hi, Mikolaj,
>>>>> XL> On 07/04/12 00:00, Mikolaj Golub wrote:
>>>>>>> Is this observed after destroying epair? There is an issue with
>>>>>>> epair: on destroy, when epair_clone_destroy() calls
>>>>>>> ether_ifdetach() for its second half it does not switch to its vnet
>>>>>>> and if_detach_internal() can't find the interface and just returns.
>>>>>>> As a result V_ifnet list is left with dead reference.
>>>>> XL> Yes.
>>>>>>> Here is an updated patch against CURRENT:
>>>>> XL> Your
>>>>> XL> patch did fixed the problem, thanks!  Are you going to commit it
>>>>> XL> against -HEAD and then MFC after a while?
>>>>> I would like Bjoern review it before me committing, or at least tell he does
>>>>> not mind, if he does not have time to review -)
>>> BAZ> To me the patch looks wrong; I am wondering if someone broke some other central
>>> BAZ> assumptions but given I cannot currently spend time on this and if it fixes things
>>> BAZ> feel free to go ahead.
>>> If you told what looks wrong I could try to dig at that direction and might be
>>> back with a better solution, instead of committing a presumably wrong fix.
> BAZ> sorry;  vnet.c:vnet_destroy() should dtrt already wrt to interfaces moving to parents
> BAZ> and being detached.
> But this is not the issue with vnet_destroy() not moving interfaces to
> parents. It does move them. It is with destroying epair. When epair that has
> its ends in different vnets is destroyed, and ether_ifdetach() is called for
> the second end without switching to its vnet it fails to find the iface in the
> wrong vnet and just silently returns (which I think is also wrong:
> if_detach_internal() should panic here). As a result the pointer is not
> removed from vnet ifnet list. And later, when someone is traversing this list
> and tries to access the pointer (this is often vnet_destroy(), which is
> usually called after removing interfaces, but might be e.g. ifconfig) dead
> pointer dereference occurs.
> My patch just makes epair_clone_destroy() switch to the proper vnet before
> calling ether_ifdetach().
> Or have I missed your point?


Situation 1)

	epairNa is in base, eiparNb is jail foo
	stop jail foo: jail -r foo
	both epairN[ab] will live in base and can be destiryed without vnet switching

Situation 2)

	epairNa is in base, eiparNb is jail foo
	you are in jail foo and type epairNb destroy;  that should not be allowed

Situation 3)

	epairNa is in base, eiparNb is jail foo
	you are in base and type ifconfig epairNa destroy

	This is your case ...  I am not sure what I'd expect in this case,
	especailly given epair is special...  You probably are right.
	Ideally I'd not allow it to be destroyed unless both are in the
	if_home_vnet.  However it seems we allow this; so in that case
	I definitively make sure to use the CURVNET_SET_QUIET() version
	to avoid the expected noise otherwise.

The moment cloners will handle this it'll all be centrally managed
and individual device drivers shouldn't need to worry about it anymore.


Bjoern A. Zeeb                                 You have to have visions!
   It does not matter how good you are. It matters what good you do!

More information about the freebsd-virtualization mailing list