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
F81981216: D20869.id.diff
Wed, Apr 24, 2:25 AM
Unknown Object (File)
Sat, Apr 20, 3:33 PM
Unknown Object (File)
Tue, Apr 16, 9:02 PM
Unknown Object (File)
Tue, Apr 16, 9:27 AM
Unknown Object (File)
Sat, Apr 6, 3:40 AM
Unknown Object (File)
Jan 12 2024, 12:39 AM
Unknown Object (File)
Jan 4 2024, 5:33 PM
Unknown Object (File)
Jan 4 2024, 5:28 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.
         */