};
 
 struct tun_file {
+       atomic_t count;
        struct tun_struct *tun;
        struct net *net;
        wait_queue_head_t       read_wait;
        err = 0;
        tfile->tun = tun;
        tun->tfile = tfile;
+       dev_hold(tun->dev);
+       atomic_inc(&tfile->count);
 
 out:
        netif_tx_unlock_bh(tun->dev);
 
        /* Drop read queue */
        skb_queue_purge(&tun->readq);
+
+       /* Drop the extra count on the net device */
+       dev_put(tun->dev);
+}
+
+static void tun_detach(struct tun_struct *tun)
+{
+       rtnl_lock();
+       __tun_detach(tun);
+       rtnl_unlock();
 }
 
 static struct tun_struct *__tun_get(struct tun_file *tfile)
 {
-       return tfile->tun;
+       struct tun_struct *tun = NULL;
+
+       if (atomic_inc_not_zero(&tfile->count))
+               tun = tfile->tun;
+
+       return tun;
 }
 
 static struct tun_struct *tun_get(struct file *file)
 
 static void tun_put(struct tun_struct *tun)
 {
-       /* Noop for now */
+       struct tun_file *tfile = tun->tfile;
+
+       if (atomic_dec_and_test(&tfile->count))
+               tun_detach(tfile->tun);
 }
 
 /* TAP filterting */
 
 static const struct ethtool_ops tun_ethtool_ops;
 
+/* Net device detach from fd. */
+static void tun_net_uninit(struct net_device *dev)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+       struct tun_file *tfile = tun->tfile;
+
+       /* Inform the methods they need to stop using the dev.
+        */
+       if (tfile) {
+               wake_up_all(&tfile->read_wait);
+               if (atomic_dec_and_test(&tfile->count))
+                       __tun_detach(tun);
+       }
+}
+
 /* Net device open. */
 static int tun_net_open(struct net_device *dev)
 {
 }
 
 static const struct net_device_ops tun_netdev_ops = {
+       .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
 };
 
 static const struct net_device_ops tap_netdev_ops = {
+       .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
        .ndo_stop               = tun_net_close,
        .ndo_start_xmit         = tun_net_xmit,
        if (!skb_queue_empty(&tun->readq))
                mask |= POLLIN | POLLRDNORM;
 
+       if (tun->dev->reg_state != NETREG_REGISTERED)
+               mask = POLLERR;
+
        tun_put(tun);
        return mask;
 }
                                ret = -ERESTARTSYS;
                                break;
                        }
+                       if (tun->dev->reg_state != NETREG_REGISTERED) {
+                               ret = -EIO;
+                               break;
+                       }
 
                        /* Nothing to read, let's sleep */
                        schedule();
        tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
        if (!tfile)
                return -ENOMEM;
+       atomic_set(&tfile->count, 0);
        tfile->tun = NULL;
        tfile->net = get_net(current->nsproxy->net_ns);
        init_waitqueue_head(&tfile->read_wait);