In the new ifioctl order, tun_ioctl() can call itself through

ifioctl_common().  Since the first tun_ioctl() call already holds
the simplelock, the second tun_ioctl() call will wait forever to
acquire it: deadlock.

To fix this, wait to acquire the lock until tuninit().
This commit is contained in:
dyoung 2008-11-20 21:54:42 +00:00
parent 7892af0d0c
commit 67852fcbc2

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_tun.c,v 1.108 2008/11/07 00:20:13 dyoung Exp $ */ /* $NetBSD: if_tun.c,v 1.109 2008/11/20 21:54:42 dyoung Exp $ */
/* /*
* Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk>
@ -15,7 +15,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.108 2008/11/07 00:20:13 dyoung Exp $"); __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.109 2008/11/20 21:54:42 dyoung Exp $");
#include "opt_inet.h" #include "opt_inet.h"
@ -388,6 +388,7 @@ tuninit(struct tun_softc *tp)
TUNDEBUG("%s: tuninit\n", ifp->if_xname); TUNDEBUG("%s: tuninit\n", ifp->if_xname);
simple_lock(&tp->tun_lock);
ifp->if_flags |= IFF_UP | IFF_RUNNING; ifp->if_flags |= IFF_UP | IFF_RUNNING;
tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR); tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
@ -426,6 +427,7 @@ tuninit(struct tun_softc *tp)
#endif /* INET6 */ #endif /* INET6 */
} }
simple_unlock(&tp->tun_lock);
return; return;
} }
@ -440,7 +442,6 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
struct ifreq *ifr = data; struct ifreq *ifr = data;
s = splnet(); s = splnet();
simple_lock(&tp->tun_lock);
switch (cmd) { switch (cmd) {
case SIOCINITIFADDR: case SIOCINITIFADDR:
@ -487,7 +488,6 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
error = ifioctl_common(ifp, cmd, data); error = ifioctl_common(ifp, cmd, data);
} }
simple_unlock(&tp->tun_lock);
splx(s); splx(s);
return (error); return (error);
} }