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>
@ -15,7 +15,7 @@
*/
#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"
@ -388,6 +388,7 @@ tuninit(struct tun_softc *tp)
TUNDEBUG("%s: tuninit\n", ifp->if_xname);
simple_lock(&tp->tun_lock);
ifp->if_flags |= IFF_UP | IFF_RUNNING;
tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
@ -426,6 +427,7 @@ tuninit(struct tun_softc *tp)
#endif /* INET6 */
}
simple_unlock(&tp->tun_lock);
return;
}
@ -440,7 +442,6 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
struct ifreq *ifr = data;
s = splnet();
simple_lock(&tp->tun_lock);
switch (cmd) {
case SIOCINITIFADDR:
@ -487,7 +488,6 @@ tun_ioctl(struct ifnet *ifp, u_long cmd, void *data)
error = ifioctl_common(ifp, cmd, data);
}
simple_unlock(&tp->tun_lock);
splx(s);
return (error);
}