Thu Mar 3 05:47:14 2022 UTC ()
usbnet: Ensure ifp->if_softc is initialized _before_ publishing ifp.

Otherwise other parts of the system might start using ifp the moment
we if_register it, and trip over null if_softc.


(riastradh)
diff -r1.47 -r1.48 src/sys/dev/usb/usbnet.c

cvs diff -r1.47 -r1.48 src/sys/dev/usb/usbnet.c (expand / switch to unified diff)

--- src/sys/dev/usb/usbnet.c 2022/03/03 05:47:06 1.47
+++ src/sys/dev/usb/usbnet.c 2022/03/03 05:47:14 1.48
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: usbnet.c,v 1.47 2022/03/03 05:47:06 riastradh Exp $ */ 1/* $NetBSD: usbnet.c,v 1.48 2022/03/03 05:47:14 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2019 Matthew R. Green 4 * Copyright (c) 2019 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Common code shared between USB network drivers. 30 * Common code shared between USB network drivers.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.47 2022/03/03 05:47:06 riastradh Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: usbnet.c,v 1.48 2022/03/03 05:47:14 riastradh Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/kmem.h> 38#include <sys/kmem.h>
39#include <sys/module.h> 39#include <sys/module.h>
40#include <sys/atomic.h> 40#include <sys/atomic.h>
41 41
42#include <dev/usb/usbnet.h> 42#include <dev/usb/usbnet.h>
43#include <dev/usb/usbhist.h> 43#include <dev/usb/usbhist.h>
44 44
45struct usbnet_cdata { 45struct usbnet_cdata {
46 struct usbnet_chain *uncd_tx_chain; 46 struct usbnet_chain *uncd_tx_chain;
47 struct usbnet_chain *uncd_rx_chain; 47 struct usbnet_chain *uncd_rx_chain;
@@ -70,26 +70,27 @@ struct usbnet_private { @@ -70,26 +70,27 @@ struct usbnet_private {
70 70
71 struct usbnet_cdata unp_cdata; 71 struct usbnet_cdata unp_cdata;
72 72
73 struct ethercom unp_ec; 73 struct ethercom unp_ec;
74 struct mii_data unp_mii; 74 struct mii_data unp_mii;
75 struct usb_task unp_mcasttask; 75 struct usb_task unp_mcasttask;
76 struct usb_task unp_ticktask; 76 struct usb_task unp_ticktask;
77 struct callout unp_stat_ch; 77 struct callout unp_stat_ch;
78 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX]; 78 struct usbd_pipe *unp_ep[USBNET_ENDPT_MAX];
79 79
80 bool unp_dying; 80 bool unp_dying;
81 bool unp_stopping; 81 bool unp_stopping;
82 bool unp_attached; 82 bool unp_attached;
 83 bool unp_ifp_attached;
83 bool unp_link; 84 bool unp_link;
84 85
85 int unp_refcnt; 86 int unp_refcnt;
86 int unp_timer; 87 int unp_timer;
87 unsigned short unp_if_flags; 88 unsigned short unp_if_flags;
88 unsigned unp_number; 89 unsigned unp_number;
89 90
90 krndsource_t unp_rndsrc; 91 krndsource_t unp_rndsrc;
91 92
92 struct timeval unp_rx_notice; 93 struct timeval unp_rx_notice;
93 struct timeval unp_tx_notice; 94 struct timeval unp_tx_notice;
94 struct timeval unp_intr_notice; 95 struct timeval unp_intr_notice;
95}; 96};
@@ -1482,63 +1483,65 @@ usbnet_attach_mii(struct usbnet *un, con @@ -1482,63 +1483,65 @@ usbnet_attach_mii(struct usbnet *un, con
1482} 1483}
1483 1484
1484void 1485void
1485usbnet_attach_ifp(struct usbnet *un, 1486usbnet_attach_ifp(struct usbnet *un,
1486 unsigned if_flags, /* additional if_flags */ 1487 unsigned if_flags, /* additional if_flags */
1487 unsigned if_extflags, /* additional if_extflags */ 1488 unsigned if_extflags, /* additional if_extflags */
1488 const struct usbnet_mii *unm) /* additional mii_attach flags */ 1489 const struct usbnet_mii *unm) /* additional mii_attach flags */
1489{ 1490{
1490 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1491 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1491 struct usbnet_private * const unp = un->un_pri; 1492 struct usbnet_private * const unp = un->un_pri;
1492 struct ifnet * const ifp = usbnet_ifp(un); 1493 struct ifnet * const ifp = usbnet_ifp(un);
1493 1494
1494 KASSERT(unp->unp_attached); 1495 KASSERT(unp->unp_attached);
 1496 KASSERT(!unp->unp_ifp_attached);
1495 1497
 1498 ifp->if_softc = un;
1496 strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ); 1499 strlcpy(ifp->if_xname, device_xname(un->un_dev), IFNAMSIZ);
1497 ifp->if_flags = if_flags; 1500 ifp->if_flags = if_flags;
1498 ifp->if_extflags = IFEF_MPSAFE | if_extflags; 1501 ifp->if_extflags = IFEF_MPSAFE | if_extflags;
1499 ifp->if_ioctl = usbnet_if_ioctl; 1502 ifp->if_ioctl = usbnet_if_ioctl;
1500 ifp->if_start = usbnet_if_start; 1503 ifp->if_start = usbnet_if_start;
1501 ifp->if_init = usbnet_if_init; 1504 ifp->if_init = usbnet_if_init;
1502 ifp->if_stop = usbnet_if_stop; 1505 ifp->if_stop = usbnet_if_stop;
1503 1506
1504 if (unm) 1507 if (unm)
1505 usbnet_attach_mii(un, unm); 1508 usbnet_attach_mii(un, unm);
1506 else 1509 else
1507 unp->unp_link = true; 1510 unp->unp_link = true;
1508 1511
1509 /* Attach the interface. */ 1512 /* Attach the interface. */
1510 if_initialize(ifp); 1513 if_initialize(ifp);
1511 if (ifp->_if_input == NULL) 1514 if (ifp->_if_input == NULL)
1512 ifp->if_percpuq = if_percpuq_create(ifp); 1515 ifp->if_percpuq = if_percpuq_create(ifp);
1513 if_register(ifp); 1516 if_register(ifp);
 1517 unp->unp_ifp_attached = true;
1514 1518
1515 /* 1519 /*
1516 * If ethernet address is all zero, skip ether_ifattach() and 1520 * If ethernet address is all zero, skip ether_ifattach() and
1517 * instead attach bpf here.. 1521 * instead attach bpf here..
1518 */ 1522 */
1519 if (!usbnet_empty_eaddr(un)) { 1523 if (!usbnet_empty_eaddr(un)) {
1520 ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb); 1524 ether_set_ifflags_cb(&unp->unp_ec, usbnet_ifflags_cb);
1521 aprint_normal_dev(un->un_dev, "Ethernet address %s\n", 1525 aprint_normal_dev(un->un_dev, "Ethernet address %s\n",
1522 ether_sprintf(un->un_eaddr)); 1526 ether_sprintf(un->un_eaddr));
1523 ether_ifattach(ifp, un->un_eaddr); 1527 ether_ifattach(ifp, un->un_eaddr);
1524 } else { 1528 } else {
1525 if_alloc_sadl(ifp); 1529 if_alloc_sadl(ifp);
1526 bpf_attach(ifp, DLT_RAW, 0); 1530 bpf_attach(ifp, DLT_RAW, 0);
1527 } 1531 }
1528 1532
1529 /* Now ready, and attached. */ 1533 /* Now ready, and attached. */
1530 IFQ_SET_READY(&ifp->if_snd); 1534 IFQ_SET_READY(&ifp->if_snd);
1531 ifp->if_softc = un; 
1532 1535
1533 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev); 1536 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, un->un_udev, un->un_dev);
1534 1537
1535 if (!pmf_device_register(un->un_dev, NULL, NULL)) 1538 if (!pmf_device_register(un->un_dev, NULL, NULL))
1536 aprint_error_dev(un->un_dev, "couldn't establish power handler\n"); 1539 aprint_error_dev(un->un_dev, "couldn't establish power handler\n");
1537} 1540}
1538 1541
1539int 1542int
1540usbnet_detach(device_t self, int flags) 1543usbnet_detach(device_t self, int flags)
1541{ 1544{
1542 USBNETHIST_FUNC(); USBNETHIST_CALLED(); 1545 USBNETHIST_FUNC(); USBNETHIST_CALLED();
1543 struct usbnet * const un = device_private(self); 1546 struct usbnet * const un = device_private(self);
1544 struct usbnet_private * const unp = un->un_pri; 1547 struct usbnet_private * const unp = un->un_pri;
@@ -1574,27 +1577,27 @@ usbnet_detach(device_t self, int flags) @@ -1574,27 +1577,27 @@ usbnet_detach(device_t self, int flags)
1574 } 1577 }
1575 mutex_exit(&unp->unp_core_lock); 1578 mutex_exit(&unp->unp_core_lock);
1576 1579
1577 usbnet_rx_list_free(un); 1580 usbnet_rx_list_free(un);
1578 usbnet_tx_list_free(un); 1581 usbnet_tx_list_free(un);
1579 1582
1580 callout_destroy(&unp->unp_stat_ch); 1583 callout_destroy(&unp->unp_stat_ch);
1581 rnd_detach_source(&unp->unp_rndsrc); 1584 rnd_detach_source(&unp->unp_rndsrc);
1582 1585
1583 if (mii) { 1586 if (mii) {
1584 mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY); 1587 mii_detach(mii, MII_PHY_ANY, MII_OFFSET_ANY);
1585 ifmedia_fini(&mii->mii_media); 1588 ifmedia_fini(&mii->mii_media);
1586 } 1589 }
1587 if (ifp->if_softc) { 1590 if (unp->unp_ifp_attached) {
1588 if (!usbnet_empty_eaddr(un)) 1591 if (!usbnet_empty_eaddr(un))
1589 ether_ifdetach(ifp); 1592 ether_ifdetach(ifp);
1590 else 1593 else
1591 bpf_detach(ifp); 1594 bpf_detach(ifp);
1592 if_detach(ifp); 1595 if_detach(ifp);
1593 } 1596 }
1594 usbnet_ec(un)->ec_mii = NULL; 1597 usbnet_ec(un)->ec_mii = NULL;
1595 1598
1596 /* 1599 /*
1597 * We have already waited for the multicast task to complete. 1600 * We have already waited for the multicast task to complete.
1598 * Unfortunately, until if_detach, nothing has prevented it 1601 * Unfortunately, until if_detach, nothing has prevented it
1599 * from running again -- another thread might issue if_mcast_op 1602 * from running again -- another thread might issue if_mcast_op
1600 * between the time of our first usb_rem_task_wait and the time 1603 * between the time of our first usb_rem_task_wait and the time