Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174467704
D57669.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D57669.diff
View Options
diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h
--- a/sys/net/if_gre.h
+++ b/sys/net/if_gre.h
@@ -117,9 +117,6 @@
#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
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -40,11 +40,13 @@
#include "opt_rss.h"
#include <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mbuf.h>
+#include <sys/osd.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/socket.h>
@@ -208,14 +210,16 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
}
- GRE_RUNLOCK();
return (error);
}
@@ -1061,18 +1074,14 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
+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 @@
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);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 4, 11:55 AM (1 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35737373
Default Alt Text
D57669.diff (7 KB)
Attached To
Mode
D57669: if_gre(4): Fix races by changing initialization order and locks
Attached
Detach File
Event Timeline
Log In to Comment