if_tuntap: make SIOCIFDESTROY interruptible

There's no good justification to permanently hang a thread until the
tunnel can be destroyed.  Make it interruptible so that the admin can
^C it and remedy the situation if something erroneously has the tunnel
open, rather than forcing them to open another shell to resolve it.

Reviewed by:	markj
Differential Revision:	https://reviews.freebsd.org/D39740
This commit is contained in:
Kyle Evans
2025-08-21 09:21:41 -05:00
parent 9f77909703
commit 274bf7c8ae
+26 -14
View File
@@ -615,19 +615,34 @@ tunclone(void *arg, struct ucred *cred, char *name, int namelen,
CURVNET_RESTORE();
}
static void
tun_destroy(struct tuntap_softc *tp)
static int
tun_destroy(struct tuntap_softc *tp, bool may_intr)
{
int error;
TUN_LOCK(tp);
MPASS((tp->tun_flags & TUN_DYING) == 0);
tp->tun_flags |= TUN_DYING;
if (tp->tun_busy != 0)
cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx);
else
TUN_UNLOCK(tp);
error = 0;
while (tp->tun_busy != 0) {
if (may_intr)
error = cv_wait_sig(&tp->tun_cv, &tp->tun_mtx);
else
cv_wait(&tp->tun_cv, &tp->tun_mtx);
if (error != 0) {
tp->tun_flags &= ~TUN_DYING;
TUN_UNLOCK(tp);
return (error);
}
}
TUN_UNLOCK(tp);
CURVNET_SET(TUN2IFP(tp)->if_vnet);
mtx_lock(&tunmtx);
TAILQ_REMOVE(&tunhead, tp, tun_list);
mtx_unlock(&tunmtx);
/* destroy_dev will take care of any alias. */
destroy_dev(tp->tun_dev);
seldrain(&tp->tun_rsel);
@@ -648,6 +663,8 @@ tun_destroy(struct tuntap_softc *tp)
cv_destroy(&tp->tun_cv);
free(tp, M_TUN);
CURVNET_RESTORE();
return (0);
}
static int
@@ -655,12 +672,7 @@ tun_clone_destroy(struct if_clone *ifc __unused, struct ifnet *ifp, uint32_t fla
{
struct tuntap_softc *tp = ifp->if_softc;
mtx_lock(&tunmtx);
TAILQ_REMOVE(&tunhead, tp, tun_list);
mtx_unlock(&tunmtx);
tun_destroy(tp);
return (0);
return (tun_destroy(tp, true));
}
static void
@@ -702,9 +714,9 @@ tun_uninit(const void *unused __unused)
mtx_lock(&tunmtx);
while ((tp = TAILQ_FIRST(&tunhead)) != NULL) {
TAILQ_REMOVE(&tunhead, tp, tun_list);
mtx_unlock(&tunmtx);
tun_destroy(tp);
/* tun_destroy() will remove it from the tailq. */
tun_destroy(tp, false);
mtx_lock(&tunmtx);
}
mtx_unlock(&tunmtx);