Subject: kern/856: tcpdump can cause kernel panic; fix included
To: None <gnats-admin@NetBSD.ORG>
From: Lon Willett <lon%softt.uucp@math.utah.edu>
List: netbsd-bugs
Date: 03/08/1995 15:20:05
>Number: 856
>Category: kern
>Synopsis: tcpdump can cause kernel panic; fix included
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Mar 8 15:20:04 1995
>Originator: Lon Willett
>Organization:
none
>Release: NetBSD-current 8 Mar 95
>Environment:
System: NetBSD hilly 1.0A NetBSD 1.0A (HILLY) #150: Wed Mar 8 13:40:25 MST 1995 lon@hilly:/usr/src/sys/arch/i386/compile/HILLY i386
>Description:
If an interface that bpf (i.e. tcpdump) has put in promiscuous mode goes
down, then when the bpf device is closed out (i.e. tcpdump exits), the
kernel panics. NB: this also includes PPP interfaces, even though they
don't have a promiscuous mode, because they are perfectly willing to let
you set the IFF_PROMISC flag without complaining.
>How-To-Repeat:
e.g. How I came across it:
# pppd ...
(now ppp0 is up)
# tcpdump -i ppp0
(now it is marked in promiscuous mode)
(interface goes down, e.g. on another tty:
# ifconfig ppp0 down # does this work? or must you kill PPPD-PID
)
Type ^C to kill tcpdump.
You should get a panic: "ifpromisc failed".
>Fix:
Here's a "diff -u" of how I fixed it. The problem is that "ifpromisc" was
checking IFF_UP too soon when turning promiscuous mode off.
--- usr/src/sys/net/bpf.c.orig Fri Feb 24 04:20:37 1995
+++ usr/src/sys/net/bpf.c Wed Mar 8 11:22:01 1995
@@ -245,8 +245,10 @@
* If so, turn it off.
*/
if (d->bd_promisc) {
+ int error;
d->bd_promisc = 0;
- if (ifpromisc(bp->bif_ifp, 0))
+ if ((error = ifpromisc(bp->bif_ifp, 0)) != 0 &&
+ error != EINVAL) /* PPP/SLIP/etc. return EINVAL */
/*
* Something is really wrong if we were able to put
* the driver into promiscuous mode, but can't
@@ -1240,14 +1242,14 @@
int pswitch;
{
struct ifreq ifr;
- /*
- * If the device is not configured up, we cannot put it in
- * promiscuous mode.
- */
- if ((ifp->if_flags & IFF_UP) == 0)
- return (ENETDOWN);
if (pswitch) {
+ /*
+ * If the device is not configured up, we cannot put it in
+ * promiscuous mode.
+ */
+ if ((ifp->if_flags & IFF_UP) == 0)
+ return (ENETDOWN);
if (ifp->if_pcount++ != 0)
return (0);
ifp->if_flags |= IFF_PROMISC;
@@ -1255,6 +1257,14 @@
if (--ifp->if_pcount > 0)
return (0);
ifp->if_flags &= ~IFF_PROMISC;
+ /*
+ * If the device is not configured up, we should not need to
+ * turn off promiscuous mode (device should have turned it
+ * off when interface went down; and will look at IFF_PROMISC
+ * again next time interface comes up).
+ */
+ if ((ifp->if_flags & IFF_UP) == 0)
+ return (0);
}
ifr.ifr_flags = ifp->if_flags;
return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
>Audit-Trail:
>Unformatted: