NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/48964: In urndis(4), initialization of ifnet structure is not enough, cause panic.
>Number: 48964
>Category: kern
>Synopsis: In urndis(4), initialization of ifnet structure is not enough,
>cause panic.
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 04 18:20:00 +0000 2014
>Originator: Yasushi Oshima
>Release: NetBSD-current 6.99.45
>Organization:
>Environment:
NetBSD jaguar 6.99.45 NetBSD 6.99.45 (GENERIC) #3: Sat Jul 5 02:30:41 JST 2014
root@sweety:/export/current/daily/20140705/obj/amd64/sys/arch/amd64/compile/GENERIC
amd64
>Description:
When running dhcpcd(4) with urndis(4), ioctl(SIOCINITIFADDR) is called and
kernel panic occurs in ether_ioctl().
urndis_ioctl(SIOCINITIFADDR) will pass through to ether_ioctl(),
ether_ioctl(SIOCINITIFADDR) will call ifp->if_init() function.
Howerver, this is NULL, wasn't set when attaching urndis(4).
note:
This problem appears with dhcpcd version 6.4.0 (or later?)
Before 6.4 case, it will call ioctl(SOCSIFFLAGS) in the first. so,
ifp->if_init() is not called by ether_ioctl().
This problem will exist in netbsd-6, but not appear.
>How-To-Repeat:
On netbsd-current kernel with fix PR kern/48963
and current's dhcpcd ver. 6.4.0 (after 2014.6.16).
1. Attach urndis(4) device
2. Run 'dhcpcd urndis0'
>Fix:
Set urndis_init() to ifp->if_init,
with change function type void to int (and also add return code)
--- if_urndis.c.old 2014-07-04 19:03:07.000000000 +0900
+++ if_urndis.c 2014-07-05 02:58:13.000000000 +0900
@@ -76,7 +76,7 @@
static int urndis_rx_list_init(struct urndis_softc *);
static int urndis_tx_list_init(struct urndis_softc *);
-static void urndis_init(struct ifnet *);
+static int urndis_init(struct ifnet *);
static void urndis_stop(struct ifnet *);
static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
@@ -1022,35 +1022,35 @@
}
#endif
-static void
+static int
urndis_init(struct ifnet *ifp)
{
struct urndis_softc *sc;
int i, s;
- usbd_status err;
+ usbd_status err=0;
sc = ifp->if_softc;
if (ifp->if_flags & IFF_RUNNING)
- return;
+ return err;
- if (urndis_ctrl_init(sc) != RNDIS_STATUS_SUCCESS)
- return;
+ if ((err=urndis_ctrl_init(sc)) != RNDIS_STATUS_SUCCESS)
+ return err;
s = splnet();
- if (urndis_tx_list_init(sc) == ENOBUFS) {
+ if ((err=urndis_tx_list_init(sc)) == ENOBUFS) {
printf("%s: tx list init failed\n",
DEVNAME(sc));
splx(s);
- return;
+ return err;
}
- if (urndis_rx_list_init(sc) == ENOBUFS) {
+ if ((err=urndis_rx_list_init(sc)) == ENOBUFS) {
printf("%s: rx list init failed\n",
DEVNAME(sc));
splx(s);
- return;
+ return err;
}
err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
@@ -1059,7 +1059,7 @@
printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
usbd_errstr(err));
splx(s);
- return;
+ return err;
}
err = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
@@ -1068,7 +1068,7 @@
printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
usbd_errstr(err));
splx(s);
- return;
+ return err;
}
for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
@@ -1086,6 +1086,7 @@
ifp->if_flags &= ~IFF_OACTIVE;
splx(s);
+ return err;
}
static void
@@ -1440,6 +1441,7 @@
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_start = urndis_start;
ifp->if_ioctl = urndis_ioctl;
+ ifp->if_init = urndis_init;
#if 0
ifp->if_watchdog = urndis_watchdog;
#endif
Home |
Main Index |
Thread Index |
Old Index