Page MenuHomeFreeBSD

D28136.id89467.diff
No OneTemporary

D28136.id89467.diff

diff --git a/sys/net/if.h b/sys/net/if.h
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -163,6 +163,7 @@
#define IFF_DYING 0x200000 /* (n) interface is winding down */
#define IFF_RENAMING 0x400000 /* (n) interface is being renamed */
#define IFF_NOGROUP 0x800000 /* (n) interface is not part of any groups */
+#define IFF_IOCTL_DRAINED 0x1000000 /* (n) control path has been drained */
/*
* Old names for driver flags so that user space tools can continue to use
@@ -177,7 +178,7 @@
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_DRV_RUNNING|IFF_DRV_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_PROMISC|\
- IFF_DYING|IFF_CANTCONFIG|IFF_KNOWSEPOCH)
+ IFF_DYING|IFF_CANTCONFIG|IFF_KNOWSEPOCH|IFF_IOCTL_DRAINED)
/*
* Values for if_link_state.
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -325,6 +325,9 @@
SX_SYSINIT_FLAGS(ifnet_detach, &ifnet_detach_sxlock, "ifnet_detach_sx",
SX_RECURSE);
+static struct sx ifnet_ioctl_sxlock;
+SX_SYSINIT_FLAGS(ifnet_ioctl, &ifnet_ioctl_sxlock, "ifnet_ioctl_sx", SX_RECURSE);
+
/*
* The allocation of network interfaces is a rather non-atomic affair; we
* need to select an index before we are ready to expose the interface for
@@ -769,6 +772,39 @@
NET_EPOCH_CALL(if_destroy, &ifp->if_epoch_ctx);
}
+/*
+ * Keep track of ifioctl() syscalls from user-space.
+ * Returns true on success and false on failure.
+ */
+bool
+if_ioctl_ref(struct ifnet *ifp)
+{
+ bool retval;
+
+ if (ifp->if_flags & IFF_IOCTL_DRAINED)
+ return (false);
+
+ sx_slock(&ifnet_ioctl_sxlock);
+ retval = (ifp->if_flags & IFF_IOCTL_DRAINED) == 0;
+ if (!retval)
+ sx_sunlock(&ifnet_ioctl_sxlock);
+ return (retval);
+}
+
+void
+if_ioctl_drain(struct ifnet *ifp)
+{
+ sx_xlock(&ifnet_ioctl_sxlock);
+ ifp->if_flags |= IFF_IOCTL_DRAINED;
+ sx_xunlock(&ifnet_ioctl_sxlock);
+}
+
+void
+if_ioctl_unref(struct ifnet *ifp)
+{
+ sx_sunlock(&ifnet_ioctl_sxlock);
+}
+
void
ifq_init(struct ifaltq *ifq, struct ifnet *ifp)
{
@@ -3039,7 +3075,13 @@
goto out_noref;
}
- error = ifhwioctl(cmd, ifp, data, td);
+ if (if_ioctl_ref(ifp)) {
+ error = ifhwioctl(cmd, ifp, data, td);
+ if_ioctl_unref(ifp);
+ } else {
+ error = ENXIO;
+ }
+
if (error != ENOIOCTL)
goto out_ref;
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -663,6 +663,9 @@
void if_ref(struct ifnet *);
void if_rele(struct ifnet *);
bool __result_use_check if_try_ref(struct ifnet *);
+bool __result_use_check if_ioctl_ref(struct ifnet *);
+void if_ioctl_drain(struct ifnet *);
+void if_ioctl_unref(struct ifnet *);
int if_setlladdr(struct ifnet *, const u_char *, int);
int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int);
void if_up(struct ifnet *);

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 24, 1:49 AM (3 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28967602
Default Alt Text
D28136.id89467.diff (2 KB)

Event Timeline