From owner-svn-src-all@freebsd.org Tue Mar 19 00:27:49 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id F0B37152A45D; Tue, 19 Mar 2019 00:27:48 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 9601585E70; Tue, 19 Mar 2019 00:27:48 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 71EAA104D; Tue, 19 Mar 2019 00:27:48 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x2J0Rmhs015348; Tue, 19 Mar 2019 00:27:48 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x2J0RmWJ015347; Tue, 19 Mar 2019 00:27:48 GMT (envelope-from kp@FreeBSD.org) Message-Id: <201903190027.x2J0RmWJ015347@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Tue, 19 Mar 2019 00:27:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r345286 - stable/11/sys/net X-SVN-Group: stable-11 X-SVN-Commit-Author: kp X-SVN-Commit-Paths: stable/11/sys/net X-SVN-Commit-Revision: 345286 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 9601585E70 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.95 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.998,0]; NEURAL_HAM_SHORT(-0.95)[-0.950,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Mar 2019 00:27:49 -0000 Author: kp Date: Tue Mar 19 00:27:48 2019 New Revision: 345286 URL: https://svnweb.freebsd.org/changeset/base/345286 Log: MFC r344794: tun: VIMAGE fix for if_tun cloner The if_tun cloner is not virtualised, but if_clone_attach() does use a virtualised list of cloners. The result is that we can't find the if_tun cloner when we try to remove a renamed tun interface. Virtualise the cloner, and move the final cleanup into a sysuninit so that we're sure this happens after all of the vnet_sysuninits Note that we need unit numbers to be system-unique (rather than unique per vnet, as is done by if_clone_simple()). The unit number is used to create the corresponding /dev/tunX device node, and this node must match with the interface. Switch to if_clone_advanced() so that we have control over the unit numbers. Reproduction scenario: jail -c -n foo persist vnet jexec test ifconfig tun create jexec test ifconfig tun0 name wg0 jexec test ifconfig wg0 destroy PR: 235704 Reviewed by: bz, hrs, hselasky Differential Revision: https://reviews.freebsd.org/D19248 Modified: stable/11/sys/net/if_tun.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/net/if_tun.c ============================================================================== --- stable/11/sys/net/if_tun.c Tue Mar 19 00:27:45 2019 (r345285) +++ stable/11/sys/net/if_tun.c Tue Mar 19 00:27:48 2019 (r345286) @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ struct tun_softc { * which is static after setup. */ static struct mtx tunmtx; +static eventhandler_tag tag; static const char tunname[] = "tun"; static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); static int tundebug = 0; @@ -129,9 +131,12 @@ static int tunoutput(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *ro); static void tunstart(struct ifnet *); -static int tun_clone_create(struct if_clone *, int, caddr_t); -static void tun_clone_destroy(struct ifnet *); -static struct if_clone *tun_cloner; +static int tun_clone_match(struct if_clone *ifc, const char *name); +static int tun_clone_create(struct if_clone *, char *, size_t, caddr_t); +static int tun_clone_destroy(struct if_clone *, struct ifnet *); +static struct unrhdr *tun_unrhdr; +VNET_DEFINE_STATIC(struct if_clone *, tun_cloner); +#define V_tun_cloner VNET(tun_cloner) static d_open_t tunopen; static d_close_t tunclose; @@ -173,11 +178,35 @@ static struct cdevsw tun_cdevsw = { }; static int -tun_clone_create(struct if_clone *ifc, int unit, caddr_t params) +tun_clone_match(struct if_clone *ifc, const char *name) { + if (strncmp(tunname, name, 3) == 0 && + (name[3] == '\0' || isdigit(name[3]))) + return (1); + + return (0); +} + +static int +tun_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) +{ struct cdev *dev; - int i; + int err, unit, i; + err = ifc_name2unit(name, &unit); + if (err != 0) + return (err); + + if (unit != -1) { + /* If this unit number is still available that/s okay. */ + if (alloc_unr_specific(tun_unrhdr, unit) == -1) + return (EEXIST); + } else { + unit = alloc_unr(tun_unrhdr); + } + + snprintf(name, IFNAMSIZ, "%s%d", tunname, unit); + /* find any existing device, or allocate new unit number */ i = clone_create(&tunclones, &tun_cdevsw, &unit, &dev, 0); if (i) { @@ -252,6 +281,7 @@ tun_destroy(struct tun_softc *tp) dev = tp->tun_dev; bpfdetach(TUN2IFP(tp)); if_detach(TUN2IFP(tp)); + free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit); if_free(TUN2IFP(tp)); destroy_dev(dev); seldrain(&tp->tun_rsel); @@ -263,8 +293,8 @@ tun_destroy(struct tun_softc *tp) CURVNET_RESTORE(); } -static void -tun_clone_destroy(struct ifnet *ifp) +static int +tun_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) { struct tun_softc *tp = ifp->if_softc; @@ -272,39 +302,64 @@ tun_clone_destroy(struct ifnet *ifp) TAILQ_REMOVE(&tunhead, tp, tun_list); mtx_unlock(&tunmtx); tun_destroy(tp); + + return (0); } +static void +vnet_tun_init(const void *unused __unused) +{ + V_tun_cloner = if_clone_advanced(tunname, 0, tun_clone_match, + tun_clone_create, tun_clone_destroy); +} +VNET_SYSINIT(vnet_tun_init, SI_SUB_PROTO_IF, SI_ORDER_ANY, + vnet_tun_init, NULL); + +static void +vnet_tun_uninit(const void *unused __unused) +{ + if_clone_detach(V_tun_cloner); +} +VNET_SYSUNINIT(vnet_tun_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, + vnet_tun_uninit, NULL); + +static void +tun_uninit(const void *unused __unused) +{ + struct tun_softc *tp; + + EVENTHANDLER_DEREGISTER(dev_clone, tag); + drain_dev_clone_events(); + + mtx_lock(&tunmtx); + while ((tp = TAILQ_FIRST(&tunhead)) != NULL) { + TAILQ_REMOVE(&tunhead, tp, tun_list); + mtx_unlock(&tunmtx); + tun_destroy(tp); + mtx_lock(&tunmtx); + } + mtx_unlock(&tunmtx); + delete_unrhdr(tun_unrhdr); + clone_cleanup(&tunclones); + mtx_destroy(&tunmtx); +} +SYSUNINIT(tun_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, tun_uninit, NULL); + static int tunmodevent(module_t mod, int type, void *data) { - static eventhandler_tag tag; - struct tun_softc *tp; switch (type) { case MOD_LOAD: mtx_init(&tunmtx, "tunmtx", NULL, MTX_DEF); clone_setup(&tunclones); + tun_unrhdr = new_unrhdr(0, IF_MAXUNIT, &tunmtx); tag = EVENTHANDLER_REGISTER(dev_clone, tunclone, 0, 1000); if (tag == NULL) return (ENOMEM); - tun_cloner = if_clone_simple(tunname, tun_clone_create, - tun_clone_destroy, 0); break; case MOD_UNLOAD: - if_clone_detach(tun_cloner); - EVENTHANDLER_DEREGISTER(dev_clone, tag); - drain_dev_clone_events(); - - mtx_lock(&tunmtx); - while ((tp = TAILQ_FIRST(&tunhead)) != NULL) { - TAILQ_REMOVE(&tunhead, tp, tun_list); - mtx_unlock(&tunmtx); - tun_destroy(tp); - mtx_lock(&tunmtx); - } - mtx_unlock(&tunmtx); - clone_cleanup(&tunclones); - mtx_destroy(&tunmtx); + /* See tun_uninit, so it's done after the vnet_sysuninit() */ break; default: return EOPNOTSUPP;