Page MenuHomeFreeBSD

vnet: Fix panic when shutting down jails and deleting interfaces simultaneously
AbandonedPublic

Authored by kp on Jul 6 2019, 5:35 PM.
Tags
None
Referenced Files
F103307962: D20869.id.diff
Sat, Nov 23, 8:56 AM
Unknown Object (File)
Thu, Nov 21, 8:12 AM
Unknown Object (File)
Wed, Nov 20, 5:03 PM
Unknown Object (File)
Wed, Nov 13, 1:00 AM
Unknown Object (File)
Thu, Oct 31, 4:39 AM
Unknown Object (File)
Oct 23 2024, 5:47 AM
Unknown Object (File)
Oct 16 2024, 9:12 PM
Unknown Object (File)
Oct 15 2024, 12:59 PM

Details

Reviewers
bz
mmacy
Group Reviewers
network
Summary

When we shut down a vnet jail its interfaces get moved back into their
original vnet. If we simultaneously delete that interface there's a
possible race where the interface is being moves while it's being
destroyed. That can result in if_vmove() attaching the interface into
the original vnet, and immediately freed. We then have a freed ifp in
V_ifnet, which will panic the next time we end up accessing it.

Don't re-attach dying interfaces.

This is frequently triggered by the automated pf tests.

Diff Detail

Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 25224
Build 23899: arc lint + arc unit

Event Timeline

Once this patch applied to a current, my build kernel failed with a

--- if.o ---
/usr/src/sys/net/if.c:1313:3: error: non-void function 'if_vmove' should return a value [-Wreturn-type]
                return;

This will likely (I've not tested) fix the compile error, but fundamentally this patch is not the right solution to the underlying problem.

diff --git a/sys/net/if.c b/sys/net/if.c
index 2a80a0bc46e..ffa1129c06a 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1308,6 +1308,10 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
        if (ifp->if_reassign != NULL)
                ifp->if_reassign(ifp, new_vnet, NULL);

+       /* Don't re-attach DYING interfaces. */
+       if (ifp->if_flags & IFF_DYING)
+               return (0);
+
        /*
         * Switch to the context of the target vnet.
         */