From nobody Thu Jul 30 18:11:52 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h9y2c4nVGz6mnDM for ; Thu, 30 Jul 2026 18:11:52 +0000 (UTC) (envelope-from git@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) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h9y2c2zwdz4D4w for ; Thu, 30 Jul 2026 18:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785435112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YC0cBoZuwBIko3lNwYzr2ZiaiFeniyIGRZcsfdHtJpA=; b=LWxfxjA24n89oRZi83xHoxw63pPOIrQL24ZhnrtOMwUA8RgozmPSsMmg2whFxleWXcyA4+ akEh9NEebgdbgrl/1H++QggjYOa6p1S3frh0wYxhRg86c8tZFYWhGGiEOiHlpUbeefhYkE wdMNeJwfy/WKpnCIfIvZ0qSCCuB7gX+Hy6vWVkQXrMBQ9/PX1J2t3kKYnnslEFrDKpjy44 44lQoiKhETJ7RtGPGT5qTmCRMKdHWukluP8MTM9L++RGtuRXm2B0uLgceMJqkAAp2p+wNx AmXd5xOcNGOtfI/9R5SqZBijnM5tIFkwoFhx0AKqNwCIPlDjbg4XDy8jSk0giQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785435112; a=rsa-sha256; cv=none; b=ojZzEPx99IhfXCtZ6bRff8k+uQ3EBjmLW3tBqFpJEEQo6xGLF8JkxLzJNqXtLzSZ8PTxMo nsOL80N532TDf0Bdkz2nb7kVtSxRsWTNSOiZGBBd+/IFVYaKX5/iBpNEAW2qYvXItXM4ph 51wyeiKSXc2PbbKF/wMs2WMyIc1ZaLs9YIVti4+5h8mGIerGCR6TdYROonRC3Q2NgN0d89 0I7eIwHXhyZa9EV/Zt3fTigvQGBo2ZtQFmo70lr7GuPVfgckCI+c3MMR4llV6t/eOntsFj 9Ca5Wfdd4k/KBsR6KO9qdBenuZrnB9BaSgSIHruqOCq/hl1Iesbx/vsl66Uv8Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785435112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YC0cBoZuwBIko3lNwYzr2ZiaiFeniyIGRZcsfdHtJpA=; b=atAkyNb9pW/YzIqA+/nIB19b06UON6Skg8tCnaZDK4ks9vBdE24uMtsMvfE7mwDDm9iOAG TUVwUzFK7vqEQbnQ2hZXgeIWFX9PAn8g5UPCFxI70XXiIgZvmenX9FPG8FmtxfRKRYuzbS YZGEcqu0+Y7/7/smfF1uEuGp1njnujlZY7zWn99jTgUz2fMwZiT7/7Nn9kb1vtCG/bGHq3 xQtENrYcuT6jdb+7gY4pA90ap7NlDksKeRqk4dC+r3/HWPF4R5+YXZnx+CO/ZHqTge90uk f7uhGr3VvUhOrsdVL+vtxLcf7WBCHyxTIVyHYq6Dl585CUdVqz5X2OMTfoYMhQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h9y2c1VSYz8SX for ; Thu, 30 Jul 2026 18:11:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3ddca by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Jul 2026 18:11:52 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Pouria Mousavizadeh Tehrani Subject: git: a0d2e5ebaa2e - main - if_gre(4): Fix races by changing initialization order and locks List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pouria X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a0d2e5ebaa2e7a8da83f593ed5459926423afa20 Auto-Submitted: auto-generated Date: Thu, 30 Jul 2026 18:11:52 +0000 Message-Id: <6a6b93e8.3ddca.39012bf@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=a0d2e5ebaa2e7a8da83f593ed5459926423afa20 commit a0d2e5ebaa2e7a8da83f593ed5459926423afa20 Author: Pouria Mousavizadeh Tehrani AuthorDate: 2026-07-30 17:48:47 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-07-30 17:51:11 +0000 if_gre(4): Fix races by changing initialization order and locks Treat if_gre like any other network drivers during module initialization by using SI_SUB_PROTO_IF. Also, destroy cloned interfaces via a prison removal callback for gre over udp. PR: 275474 Reviewed by: markj Discussed with: glebius Differential Revision: https://reviews.freebsd.org/D57669 --- sys/net/if_gre.c | 96 ++++++++++++++++++++++++++++++++++++-------------------- sys/net/if_gre.h | 3 -- 2 files changed, 62 insertions(+), 37 deletions(-) diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 563478eb67f8..1dc82238c6ab 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -40,11 +40,13 @@ #include "opt_rss.h" #include +#include #include #include #include #include #include +#include #include #include #include @@ -208,14 +210,16 @@ vnet_gre_init(const void *unused __unused) in6_gre_init(); #endif } -VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, - vnet_gre_init, NULL); +VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IF, SI_ORDER_ANY, vnet_gre_init, NULL); static void vnet_gre_uninit(const void *unused __unused) { - ifc_detach_cloner(V_gre_cloner); + if (V_gre_cloner != NULL) { + ifc_detach_cloner(V_gre_cloner); + V_gre_cloner = NULL; + } #ifdef INET in_gre_uninit(); #endif @@ -224,8 +228,8 @@ vnet_gre_uninit(const void *unused __unused) #endif /* XXX: epoch_call drain */ } -VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, - vnet_gre_uninit, NULL); +VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY, vnet_gre_uninit, + NULL); static int gre_clone_create_nl(struct if_clone *ifc, char *name, size_t len, @@ -248,7 +252,7 @@ gre_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd) struct nl_parsed_gre params; struct nlattr *attrs = lattrs->ifla_idata; struct nlattr_bmask bm; - int error = 0; + int error; if ((attrs == NULL) || (nl_has_attr(ifd->bm, IFLA_LINKINFO) == 0)) { @@ -267,6 +271,11 @@ gre_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd) if ((error = nl_parse_nested(attrs, &gre_modify_parser, npt, ¶ms)) != 0) return (error); + sx_xlock(&gre_ioctl_sx); + sc = ifp->if_softc; + if (sc == NULL) + goto generic; + if (nl_has_attr(&bm, IFLA_GRE_LOCAL) && nl_has_attr(&bm, IFLA_GRE_REMOTE)) error = gre_set_addr_nl(sc, npt, params.ifla_local, params.ifla_remote); else if (nl_has_attr(&bm, IFLA_GRE_LOCAL) || nl_has_attr(&bm, IFLA_GRE_REMOTE)) { @@ -286,6 +295,9 @@ gre_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd) if (error == 0 && nl_has_attr(&bm, IFLA_GRE_ENCAP_SPORT)) error = gre_set_udp_sport_nl(sc, npt, params.ifla_encap_sport); +generic: + sx_xunlock(&gre_ioctl_sx); + if (error == 0) error = nl_modify_ifp_generic(ifp, ifd->lattrs, ifd->bm, ifd->npt); @@ -295,7 +307,6 @@ gre_clone_modify_nl(struct ifnet *ifp, struct ifc_data_nl *ifd) static void gre_clone_dump_nl(struct ifnet *ifp, struct nl_writer *nw) { - GRE_RLOCK_TRACKER; struct gre_softc *sc; nlattr_add_u32(nw, IFLA_LINK, ifp->if_index); @@ -312,8 +323,10 @@ gre_clone_dump_nl(struct ifnet *ifp, struct nl_writer *nw) return; } + sx_slock(&gre_ioctl_sx); sc = ifp->if_softc; - GRE_RLOCK(); + if (sc == NULL) + goto ret; if (sc->gre_family == AF_INET) { #ifdef INET @@ -343,10 +356,11 @@ gre_clone_dump_nl(struct ifnet *ifp, struct nl_writer *nw) sc->gre_options & GRE_UDPENCAP ? IFLA_TUNNEL_GRE_UDP : IFLA_TUNNEL_NONE); nlattr_add_u16(nw, IFLA_GRE_ENCAP_SPORT, sc->gre_port); +ret: nlattr_set_len(nw, off2); nlattr_set_len(nw, off); - GRE_RUNLOCK(); + sx_sunlock(&gre_ioctl_sx); } static int @@ -391,6 +405,7 @@ gre_reassign(struct ifnet *ifp, struct vnet *new_vnet __unused, if (sc != NULL) gre_delete_tunnel(sc); sx_xunlock(&gre_ioctl_sx); + if_link_state_change(ifp, LINK_STATE_DOWN); } #endif /* VIMAGE */ @@ -402,10 +417,11 @@ gre_clone_destroy(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags) sx_xlock(&gre_ioctl_sx); sc = ifp->if_softc; gre_delete_tunnel(sc); - bpfdetach(ifp); - if_detach(ifp); ifp->if_softc = NULL; sx_xunlock(&gre_ioctl_sx); + if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN); + bpfdetach(ifp); + if_detach(ifp); GRE_WAIT(); if_free(ifp); @@ -627,7 +643,7 @@ gre_delete_tunnel(struct gre_softc *sc) { struct gre_socket *gs; - sx_assert(&gre_ioctl_sx, SA_XLOCKED); + GRE_LOCK_ASSERT(); if (sc->gre_family != 0) { CK_LIST_REMOVE(sc, chain); CK_LIST_REMOVE(sc, srchash); @@ -646,7 +662,6 @@ gre_delete_tunnel(struct gre_softc *sc) sc->gre_so = NULL; } GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING; - if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN); } struct gre_list * @@ -911,7 +926,6 @@ gre_flowid(struct gre_softc *sc, struct mbuf *m, uint32_t af) static int gre_transmit(struct ifnet *ifp, struct mbuf *m) { - GRE_RLOCK_TRACKER; struct gre_softc *sc; struct grehdr *gh; struct udphdr *uh; @@ -919,8 +933,8 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) int error, len; uint16_t proto; + NET_EPOCH_ASSERT(); len = 0; - GRE_RLOCK(); #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); if (error) { @@ -1028,7 +1042,6 @@ drop: if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, len); } - GRE_RUNLOCK(); return (error); } @@ -1061,18 +1074,14 @@ gre_set_addr_nl(struct gre_softc *sc, struct nl_pstate *npt, else if (src->sa_family == AF_INET) { memcpy(&aliasreq.in.ifra_addr, src, sizeof(struct sockaddr_in)); memcpy(&aliasreq.in.ifra_dstaddr, dst, sizeof(struct sockaddr_in)); - sx_xlock(&gre_ioctl_sx); error = in_gre_ioctl(sc, SIOCSIFPHYADDR, (caddr_t)&aliasreq.in); - sx_xunlock(&gre_ioctl_sx); } #endif #ifdef INET6 else if (src->sa_family == AF_INET6) { memcpy(&aliasreq.in6.ifra_addr, src, sizeof(struct sockaddr_in6)); memcpy(&aliasreq.in6.ifra_dstaddr, dst, sizeof(struct sockaddr_in6)); - sx_xlock(&gre_ioctl_sx); error = in6_gre_ioctl(sc, SIOCSIFPHYADDR_IN6, (caddr_t)&aliasreq.in6); - sx_xunlock(&gre_ioctl_sx); } #endif else @@ -1091,11 +1100,9 @@ gre_set_addr_nl(struct gre_softc *sc, struct nl_pstate *npt, static int gre_set_flags_nl(struct gre_softc *sc, struct nl_pstate *npt, uint32_t opt) { - int error = 0; + int error; - sx_xlock(&gre_ioctl_sx); error = gre_set_flags(sc, opt); - sx_xunlock(&gre_ioctl_sx); if (error == EINVAL) nlmsg_report_err_msg(npt, "gre flags are invalid"); @@ -1106,11 +1113,9 @@ gre_set_flags_nl(struct gre_softc *sc, struct nl_pstate *npt, uint32_t opt) static int gre_set_key_nl(struct gre_softc *sc, struct nl_pstate *npt, uint32_t key) { - int error = 0; + int error; - sx_xlock(&gre_ioctl_sx); error = gre_set_key(sc, key); - sx_xunlock(&gre_ioctl_sx); if (error == EINVAL) nlmsg_report_err_msg(npt, "gre key is invalid: %u", key); @@ -1122,16 +1127,15 @@ static int gre_set_encap_nl(struct gre_softc *sc, struct nl_pstate *npt, uint32_t type) { uint32_t opt; - int error = 0; + int error; - sx_xlock(&gre_ioctl_sx); opt = sc->gre_options; if (type & IFLA_TUNNEL_GRE_UDP) opt |= GRE_UDPENCAP; else opt &= ~GRE_UDPENCAP; + error = gre_set_flags(sc, opt); - sx_xunlock(&gre_ioctl_sx); if (error == EEXIST) nlmsg_report_err_msg(npt, "same gre tunnel exist"); @@ -1143,11 +1147,9 @@ gre_set_encap_nl(struct gre_softc *sc, struct nl_pstate *npt, uint32_t type) static int gre_set_udp_sport_nl(struct gre_softc *sc, struct nl_pstate *npt, uint16_t port) { - int error = 0; + int error; - sx_xlock(&gre_ioctl_sx); error = gre_set_udp_sport(sc, port); - sx_xunlock(&gre_ioctl_sx); if (error == EINVAL) nlmsg_report_err_msg(npt, "source port is invalid: %u", port); @@ -1156,15 +1158,41 @@ gre_set_udp_sport_nl(struct gre_softc *sc, struct nl_pstate *npt, uint16_t port) } +static int +gre_prison_remove(void *obj, void *data __unused) +{ +#ifdef VIMAGE + struct prison *pr; + + pr = obj; + if (prison_owns_vnet(pr)) { + CURVNET_SET(pr->pr_vnet); + if (V_gre_cloner != NULL) + vnet_gre_uninit(NULL); + CURVNET_RESTORE(); + } +#endif + return (0); +} + + static int gremodevent(module_t mod, int type, void *data) { + static int gre_osd_jail_slot; switch (type) { - case MOD_LOAD: + case MOD_LOAD: { + osd_method_t methods[PR_MAXMETHOD] = { + [PR_METHOD_REMOVE] = gre_prison_remove, + }; + gre_osd_jail_slot = osd_jail_register(NULL, methods); NL_VERIFY_PARSERS(all_parsers); break; + } case MOD_UNLOAD: + if (gre_osd_jail_slot != 0) + osd_jail_deregister(gre_osd_jail_slot); break; default: return (EOPNOTSUPP); @@ -1178,5 +1206,5 @@ static moduledata_t gre_mod = { 0 }; -DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); +DECLARE_MODULE(if_gre, gre_mod, SI_SUB_PROTO_IF, SI_ORDER_ANY); MODULE_VERSION(if_gre, 1); diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h index ae6d18385dfb..61c8ef54523e 100644 --- a/sys/net/if_gre.h +++ b/sys/net/if_gre.h @@ -117,9 +117,6 @@ MALLOC_DECLARE(M_GRE); #endif #define GRE2IFP(sc) ((sc)->gre_ifp) -#define GRE_RLOCK_TRACKER struct epoch_tracker gre_et -#define GRE_RLOCK() epoch_enter_preempt(net_epoch_preempt, &gre_et) -#define GRE_RUNLOCK() epoch_exit_preempt(net_epoch_preempt, &gre_et) #define GRE_WAIT() epoch_wait_preempt(net_epoch_preempt) #define gre_hdr gre_uhdr.hdr