Subject: kern/27678: destroying if_wm.c vlans with ifconfig can crash system
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <chuck@ece.cmu.edu>
List: netbsd-bugs
Date: 10/29/2004 22:35:55
>Number: 27678
>Category: kern
>Synopsis: destroying if_wm.c vlans with ifconfig can crash system
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: kern-bug-people
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Oct 30 02:38:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Chuck Cranor
>Release: NetBSD 2.0_RC4
>Organization:
Carnegie Mellon University
>Environment:
System: NetBSD bum.pdl.cmu.edu 2.0_RC4 NetBSD 2.0_RC4 (GENERIC) #5: Thu Oct 28 22:03:22 UTC 2004 isildur@bum.pdl.cmu.edu:/home/netbsd/20/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
we have a 2.0_RC4 system with a wm0 ethernet interface that is
connected to a switch with 2 vlans (vlan0, vlan1). the wm0
interface is configured as "up" in /etc/rc.conf, and the vlan0
and vlan1 interfaces are configured using /etc/ifconfig.vlan{0,1}.
with this config, running "/etc/rc.d/network stop" crashes the
system. this is because the script does "ifconfig wm0 down"
before unconfiguring the vlan interfaces.
when the script attempts to "ifconfig <vlan> destroy" the final
vlan associated with wm0 (which is already shut down), the following
call stack occurs:
if_clone_destroy
-> vlan_clone_destroy
-> vlan_unconfig
-> vlan_ether_purgemulti
-> wm_ioctl /* command == SIOCDELMULTI */
wm_ioctl() has the following code:
error = ether_ioctl(ifp, cmd, data);
if (error == ENETRESET) {
/*
* Multicast list has changed; set the hardware filter
* accordingly.
*/
wm_set_filter(sc);
error = 0;
}
this code results in 'wm_set_filter(sc)' for wm0 getting called,
even though the wm0 interface is already down (!RUNNING).
unfortunately, the wm_set_filter() call enables receive interrupts
on wm0 even though the interface is down. when the first receive
interrupt occurs, it tries to do mbuf operations without having
any receive ring allocated (again, because the interface is supposed
to be down).
this results in a reference though a NULL mbuf pointer and a
kernel panic.
>How-To-Repeat:
configure up a wm0, vlan0, vlan1. running the following commands
(this is what '/etc/rc.d/network stop' does):
ifconfig wm0 down
ifconfig wm0 destroy
ifconfig vlan1 down
ifconfig vlan1 destroy
ifconfig vlan0 down
ifconfig vlan0 destroy
the system will panic after the final destroy command as soon
as a receive interrupt occurs.
>Fix:
do not call wm_set_filter() on interfaces that are not IFF_RUNNING.
the hardware should be reset and multicast filters set if/when the
interface is brought up.
note that other network interface drivers besides if_wm.c should
be inspected for this problem.
>Release-Note:
>Audit-Trail:
>Unformatted: