summaryrefslogtreecommitdiff
path: root/sys/net/if_tun.c
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2009-02-20 12:47:58 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2009-02-20 12:47:58 +0000
commit8a40f245500d864a8aa008f8bb4e2fc61d6994d2 (patch)
treeb9efb39205ad6aae69ee416f58bbddd14a7d7b01 /sys/net/if_tun.c
parente55e994ccda27e04666ed3d8cce062880d2d1475 (diff)
Ensure that bpf_mtap() is always called at the same interrupt priority
level within the tun(4) driver. Otherwise we can be interrupted whilst copying a packet into the BPF buffer, leading to a race between bpf_mtap() calls. This can result in corruption within the BPF buffers. Also ensure that we are at IPL_NET when calling ether_input_mbuf(). Fixes PR6073. ok claudio@, canacar@ (for an earlier version of this diff)
Diffstat (limited to 'sys/net/if_tun.c')
-rw-r--r--sys/net/if_tun.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index 9b37e7ab460..5123e9c2ed0 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tun.c,v 1.95 2008/10/02 20:21:14 brad Exp $ */
+/* $OpenBSD: if_tun.c,v 1.96 2009/02/20 12:47:57 jsing Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
@@ -556,13 +556,14 @@ tun_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
af = mtod(m0, u_int32_t *);
*af = htonl(dst->sa_family);
+ s = splnet();
+
#if NBPFILTER > 0
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
#endif
len = m0->m_pkthdr.len;
- s = splnet();
IFQ_ENQUEUE(&ifp->if_snd, m0, NULL, error);
if (error) {
splx(s);
@@ -852,16 +853,23 @@ tunwrite(dev_t dev, struct uio *uio, int ioflag)
top->m_pkthdr.rcvif = ifp;
#if NBPFILTER > 0
- if (ifp->if_bpf)
+ if (ifp->if_bpf) {
+ s = splnet();
bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
+ splx(s);
+ }
#endif
if (tp->tun_flags & TUN_LAYER2) {
/* quirk to not add randomness from a virtual device */
atomic_setbits_int(&netisr, (1 << NETISR_RND_DONE));
+ s = splnet();
ether_input_mbuf(ifp, top);
+ splx(s);
+
ifp->if_ipackets++; /* ibytes are counted in ether_input */
+
return (0);
}
@@ -1088,6 +1096,8 @@ tunstart(struct ifnet *ifp)
struct tun_softc *tp = ifp->if_softc;
struct mbuf *m;
+ splassert(IPL_NET);
+
if (!(tp->tun_flags & TUN_LAYER2) &&
!ALTQ_IS_ENABLED(&ifp->if_snd) &&
!TBR_IS_ENABLED(&ifp->if_snd))