diff options
author | brian <brian@FreeBSD.org> | 2001-06-20 10:06:28 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 2001-06-20 10:06:28 +0000 |
commit | fcb8a3a2e689c0a1aa317b24fc10b7e3b42fa1d4 (patch) | |
tree | 7cd7432ed74414cdac2bf0900fdcbba3fccfbfeb /sys/net | |
parent | 9f7dbbc5e360447f2f66edcb39f1a20c6314e738 (diff) | |
download | FreeBSD-src-fcb8a3a2e689c0a1aa317b24fc10b7e3b42fa1d4.zip FreeBSD-src-fcb8a3a2e689c0a1aa317b24fc10b7e3b42fa1d4.tar.gz |
Close a race where we were releasing the unit resource at the start
of tunclose() rather than the end, and tunopen() grabbed that unit
before tunclose() finished (one process is allocating it while another
is freeing it!).
It may be worth hanging some sort of rw mutex around all specinfo
calls where d_close and the detach handler get a write lock and all
other functions get a read lock. This would guarantee certain levels
of ``atomicity'' (is that a word?) that people may expect (I believe
Solaris does something like this).
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_tun.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 0194995..68cef88 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -307,8 +307,7 @@ tunclose(dev_t dev, int foo, int bar, struct proc *p) tp = dev->si_drv1; ifp = &tp->tun_if; - err = rman_release_resource(tp->r_unit); - KASSERT(err == 0, ("Unit %d not marked open", ifp->if_unit)); + KASSERT(tp->r_unit, ("Unit %d not marked open", ifp->if_unit)); tp->tun_flags &= ~TUN_OPEN; tp->tun_pid = 0; @@ -340,6 +339,9 @@ tunclose(dev_t dev, int foo, int bar, struct proc *p) selwakeup(&tp->tun_rsel); TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); + err = rman_release_resource(tp->r_unit); + KASSERT(err == 0, ("Unit %d failed to release", ifp->if_unit)); + return (0); } |