Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 May 2017 20:00:02 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r318677 - in head/sys: compat/ndis dev/if_ndis
Message-ID:  <201705222000.v4MK02BJ081903@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Mon May 22 20:00:01 2017
New Revision: 318677
URL: https://svnweb.freebsd.org/changeset/base/318677

Log:
  Fix regression in ndis(4) after r286410. This adds a bunch of checks for
  whether this is a Ethernet or 802.11 device and does proper dereferencing.
  
  PR:		213237
  Submitted by:	<ota j.email.ne.jp>
  MFC after:	2 weeks

Modified:
  head/sys/compat/ndis/kern_ndis.c
  head/sys/compat/ndis/subr_ndis.c
  head/sys/dev/if_ndis/if_ndis.c
  head/sys/dev/if_ndis/if_ndisvar.h

Modified: head/sys/compat/ndis/kern_ndis.c
==============================================================================
--- head/sys/compat/ndis/kern_ndis.c	Mon May 22 19:57:28 2017	(r318676)
+++ head/sys/compat/ndis/kern_ndis.c	Mon May 22 20:00:01 2017	(r318677)
@@ -210,8 +210,8 @@ ndis_status_func(adapter, status, sbuf, 
 
 	block = adapter;
 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
-	ifp = sc->ifp;
-	if (ifp->if_flags & IFF_DEBUG)
+	ifp = NDISUSB_GET_IFNET(sc);
+	if ( ifp && ifp->if_flags & IFF_DEBUG)
 		device_printf(sc->ndis_dev, "status: %x\n", status);
 }
 
@@ -225,8 +225,8 @@ ndis_statusdone_func(adapter)
 
 	block = adapter;
 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
-	ifp = sc->ifp;
-	if (ifp->if_flags & IFF_DEBUG)
+	ifp = NDISUSB_GET_IFNET(sc);
+	if (ifp && ifp->if_flags & IFF_DEBUG)
 		device_printf(sc->ndis_dev, "status complete\n");
 }
 
@@ -264,9 +264,9 @@ ndis_resetdone_func(ndis_handle adapter,
 
 	block = adapter;
 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
-	ifp = sc->ifp;
+	ifp = NDISUSB_GET_IFNET(sc);
 
-	if (ifp->if_flags & IFF_DEBUG)
+	if (ifp && ifp->if_flags & IFF_DEBUG)
 		device_printf(sc->ndis_dev, "reset done...\n");
 	KeSetEvent(&block->nmb_resetevent, IO_NO_INCREMENT, FALSE);
 }
@@ -285,6 +285,9 @@ ndis_create_sysctls(arg)
 		return (EINVAL);
 
 	sc = arg;
+	/*
+	device_printf(sc->ndis_dev, "ndis_create_sysctls() sc=%p\n", sc);
+	*/
 	vals = sc->ndis_regvals;
 
 	TAILQ_INIT(&sc->ndis_cfglist_head);
@@ -698,8 +701,8 @@ ndis_ptom(m0, p)
 	 */
 
 	eh = mtod((*m0), struct ether_header *);
-	ifp = ((struct ndis_softc *)p->np_softc)->ifp;
-	if (totlen > ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE)) {
+	ifp = NDISUSB_GET_IFNET((struct ndis_softc *)p->np_softc);
+	if (ifp && totlen > ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE)) {
 		diff = totlen - ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE);
 		totlen -= diff;
 		m->m_len -= diff;

Modified: head/sys/compat/ndis/subr_ndis.c
==============================================================================
--- head/sys/compat/ndis/subr_ndis.c	Mon May 22 19:57:28 2017	(r318676)
+++ head/sys/compat/ndis/subr_ndis.c	Mon May 22 20:00:01 2017	(r318677)
@@ -626,6 +626,9 @@ NdisReadConfiguration(status, parm, cfg,
 
 	block = (ndis_miniport_block *)cfg;
 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+	/*
+	device_printf(sc->ndis_dev, "NdisReadConfiguration sc=%p\n", sc);
+	*/
 
 	if (key->us_len == 0 || key->us_buf == NULL) {
 		*status = NDIS_STATUS_FAILURE;
@@ -984,7 +987,7 @@ NdisWriteErrorLogEntry(ndis_handle adapt
 	dev = block->nmb_physdeviceobj->do_devext;
 	drv = block->nmb_deviceobj->do_drvobj;
 	sc = device_get_softc(dev);
-	ifp = sc->ifp;
+	ifp = NDISUSB_GET_IFNET(sc);
 
 	if (ifp != NULL && ifp->if_flags & IFF_DEBUG) {
 		error = pe_get_message((vm_offset_t)drv->dro_driverstart,
@@ -1304,17 +1307,19 @@ NdisReadNetworkAddress(status, addr, add
 	ndis_handle		adapter;
 {
 	struct ndis_softc	*sc;
+	struct ifnet		*ifp;
 	ndis_miniport_block	*block;
 	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
 
 	block = (ndis_miniport_block *)adapter;
 	sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
-	if (sc->ifp == NULL) {
+	ifp = NDISUSB_GET_IFNET(sc);
+	if (ifp == NULL) {
 		*status = NDIS_STATUS_FAILURE;
 		return;
 	}
 
-	if (sc->ifp->if_addr == NULL ||
+	if (ifp->if_addr == NULL ||
 	    bcmp(IF_LLADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0)
 		*status = NDIS_STATUS_FAILURE;
 	else {

Modified: head/sys/dev/if_ndis/if_ndis.c
==============================================================================
--- head/sys/dev/if_ndis/if_ndis.c	Mon May 22 19:57:28 2017	(r318676)
+++ head/sys/dev/if_ndis/if_ndis.c	Mon May 22 20:00:01 2017	(r318677)
@@ -147,7 +147,7 @@ static funcptr ndis_rxeof_xfr_done_wrap;
 static funcptr ndis_linksts_wrap;
 static funcptr ndis_linksts_done_wrap;
 static funcptr ndis_ticktask_wrap;
-static funcptr ndis_starttask_wrap;
+static funcptr ndis_ifstarttask_wrap;
 static funcptr ndis_resettask_wrap;
 static funcptr ndis_inputtask_wrap;
 
@@ -162,11 +162,11 @@ static int ndis_raw_xmit	(struct ieee802
 	const struct ieee80211_bpf_params *);
 static void ndis_update_mcast	(struct ieee80211com *);
 static void ndis_update_promisc	(struct ieee80211com *);
-static void ndis_start		(struct ifnet *);
-static void ndis_starttask	(device_object *, void *);
+static void ndis_ifstart	(struct ifnet *);
+static void ndis_ifstarttask	(device_object *, void *);
 static void ndis_resettask	(device_object *, void *);
 static void ndis_inputtask	(device_object *, void *);
-static int ndis_ioctl		(struct ifnet *, u_long, caddr_t);
+static int ndis_ifioctl		(struct ifnet *, u_long, caddr_t);
 static int ndis_newstate	(struct ieee80211vap *, enum ieee80211_state,
 	int);
 static int ndis_nettype_chan	(uint32_t);
@@ -246,7 +246,7 @@ ndisdrv_modevent(mod, cmd, arg)
 		    &ndis_linksts_done_wrap, 1, WINDRV_WRAP_STDCALL);
 		windrv_wrap((funcptr)ndis_ticktask, &ndis_ticktask_wrap,
 		    2, WINDRV_WRAP_STDCALL);
-		windrv_wrap((funcptr)ndis_starttask, &ndis_starttask_wrap,
+		windrv_wrap((funcptr)ndis_ifstarttask, &ndis_ifstarttask_wrap,
 		    2, WINDRV_WRAP_STDCALL);
 		windrv_wrap((funcptr)ndis_resettask, &ndis_resettask_wrap,
 		    2, WINDRV_WRAP_STDCALL);
@@ -268,7 +268,7 @@ ndisdrv_modevent(mod, cmd, arg)
 		windrv_unwrap(ndis_linksts_wrap);
 		windrv_unwrap(ndis_linksts_done_wrap);
 		windrv_unwrap(ndis_ticktask_wrap);
-		windrv_unwrap(ndis_starttask_wrap);
+		windrv_unwrap(ndis_ifstarttask_wrap);
 		windrv_unwrap(ndis_resettask_wrap);
 		windrv_unwrap(ndis_inputtask_wrap);
 		break;
@@ -292,11 +292,14 @@ ndis_setmulti(sc)
 	int			len, mclistsz, error;
 	uint8_t			*mclist;
 
-	ifp = sc->ifp;
 
 	if (!NDIS_INITIALIZED(sc))
 		return;
 
+	if (sc->ndis_80211)
+		return;
+
+	ifp = sc->ifp;
 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
 		sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
 		len = sizeof(sc->ndis_filter);
@@ -368,13 +371,14 @@ ndis_set_offload(sc)
 	struct ifnet		*ifp;
 	int			len, error;
 
-	ifp = sc->ifp;
-
 	if (!NDIS_INITIALIZED(sc))
 		return (EINVAL);
 
+	if (sc->ndis_80211)
+		return (EINVAL);
 	/* See if there's anything to set. */
 
+	ifp = sc->ifp;
 	error = ndis_probe_offload(sc);
 	if (error)
 		return (error);
@@ -965,8 +969,8 @@ ndis_ifattach(struct ndis_softc *sc)
 	if_initname(ifp, device_get_name(sc->ndis_dev),
 	    device_get_unit(sc->ndis_dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_ioctl = ndis_ioctl;
-	ifp->if_start = ndis_start;
+	ifp->if_ioctl = ndis_ifioctl;
+	ifp->if_start = ndis_ifstart;
 	ifp->if_init = ndis_init;
 	ifp->if_baudrate = 10000000;
 	IFQ_SET_MAXLEN(&ifp->if_snd, 50);
@@ -1560,19 +1564,23 @@ ndis_txeof(adapter, packet, status)
 	sc->ndis_txarray[idx] = NULL;
 	sc->ndis_txpending++;
 
-	if (status == NDIS_STATUS_SUCCESS)
-		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-	else
-		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-
+	if (!sc->ndis_80211) {
+		struct ifnet		*ifp = sc->ifp;
+		if (status == NDIS_STATUS_SUCCESS)
+			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+		else
+			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+	}
 	sc->ndis_tx_timer = 0;
-	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
 	NDIS_UNLOCK(sc);
 
-	IoQueueWorkItem(sc->ndis_startitem,
-	    (io_workitem_func)ndis_starttask_wrap,
-	    WORKQUEUE_CRITICAL, ifp);
+	if (!sc->ndis_80211)
+		IoQueueWorkItem(sc->ndis_startitem,
+		    (io_workitem_func)ndis_ifstarttask_wrap,
+		    WORKQUEUE_CRITICAL, sc);
+	DPRINTF(("%s: ndis_ifstarttask_wrap sc=%p\n", __func__, sc));
 }
 
 static void
@@ -1635,9 +1643,10 @@ ndis_linksts_done(adapter)
 		IoQueueWorkItem(sc->ndis_tickitem, 
 		    (io_workitem_func)ndis_ticktask_wrap,
 		    WORKQUEUE_CRITICAL, sc);
-		IoQueueWorkItem(sc->ndis_startitem,
-		    (io_workitem_func)ndis_starttask_wrap,
-		    WORKQUEUE_CRITICAL, ifp);
+		if (!sc->ndis_80211)
+			IoQueueWorkItem(sc->ndis_startitem,
+			    (io_workitem_func)ndis_ifstarttask_wrap,
+			    WORKQUEUE_CRITICAL, sc);
 		break;
 	case NDIS_STATUS_MEDIA_DISCONNECT:
 		if (sc->ndis_link)
@@ -1672,9 +1681,10 @@ ndis_tick(xsc)
 		IoQueueWorkItem(sc->ndis_resetitem,
 		    (io_workitem_func)ndis_resettask_wrap,
 		    WORKQUEUE_CRITICAL, sc);
-		IoQueueWorkItem(sc->ndis_startitem,
-		    (io_workitem_func)ndis_starttask_wrap,
-		    WORKQUEUE_CRITICAL, sc->ifp);
+		if (!sc->ndis_80211)
+			IoQueueWorkItem(sc->ndis_startitem,
+			    (io_workitem_func)ndis_ifstarttask_wrap,
+			    WORKQUEUE_CRITICAL, sc);
 	}
 
 	callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
@@ -1796,16 +1806,16 @@ ndis_update_promisc(struct ieee80211com 
 }
 
 static void
-ndis_starttask(d, arg)
-	device_object		*d;
-	void			*arg;
+ndis_ifstarttask(device_object *d, void *arg)
 {
-	struct ifnet		*ifp;
-
-	ifp = arg;
+	struct ndis_softc	*sc = arg;
+	DPRINTF(("%s: sc=%p, ifp=%p\n", __func__, sc, sc->ifp));
+	if (sc->ndis_80211)
+		return;
 
+	struct ifnet		*ifp = sc->ifp;
 	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-		ndis_start(ifp);
+		ndis_ifstart(ifp);
 }
 
 /*
@@ -1821,8 +1831,7 @@ ndis_starttask(d, arg)
  * will do the mapping themselves on a buffer by buffer basis.
  */
 static void
-ndis_start(ifp)
-	struct ifnet		*ifp;
+ndis_ifstart(struct ifnet *ifp)
 {
 	struct ndis_softc	*sc;
 	struct mbuf		*m = NULL;
@@ -2880,7 +2889,7 @@ ndis_getstate_80211(struct ndis_softc *s
 }
 
 static int
-ndis_ioctl(ifp, command, data)
+ndis_ifioctl(ifp, command, data)
 	struct ifnet		*ifp;
 	u_long			command;
 	caddr_t			data;

Modified: head/sys/dev/if_ndis/if_ndisvar.h
==============================================================================
--- head/sys/dev/if_ndis/if_ndisvar.h	Mon May 22 19:57:28 2017	(r318676)
+++ head/sys/dev/if_ndis/if_ndisvar.h	Mon May 22 20:00:01 2017	(r318677)
@@ -152,6 +152,7 @@ struct ndisusb_task {
 };
 
 struct ndis_softc {
+#define        NDISUSB_GET_IFNET(ndis_softc) ( (ndis_softc)->ndis_80211 ? NULL : (ndis_softc)->ifp )
 	u_int			ndis_80211:1,
 				ndis_link:1,
 				ndis_running:1;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705222000.v4MK02BJ081903>