From 83c1f36f9880814b24cdf6c2f91f66f61db65326 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Tue, 10 Apr 2018 16:28:56 +0200 Subject: [PATCH] tun: send netlink notification when the device is modified I added dumping of link information about tun devices over netlink in commit 1ec010e70593 ("tun: export flags, uid, gid, queue information over netlink"), but didn't add the missing netlink notifications when the device's exported properties change. This patch adds notifications when owner/group or flags are modified, when queues are attached/detached, and when a tun fd is closed. Reported-by: Thomas Haller Fixes: 1ec010e70593 ("tun: export flags, uid, gid, queue information over netlink") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller --- drivers/net/tun.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index c9e68fd76a37..28583aa0c17d 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -743,8 +743,15 @@ static void __tun_detach(struct tun_file *tfile, bool clean) static void tun_detach(struct tun_file *tfile, bool clean) { + struct tun_struct *tun; + struct net_device *dev; + rtnl_lock(); + tun = rtnl_dereference(tfile->tun); + dev = tun ? tun->dev : NULL; __tun_detach(tfile, clean); + if (dev) + netdev_state_change(dev); rtnl_unlock(); } @@ -2562,13 +2569,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) /* One or more queue has already been attached, no need * to initialize the device again. */ + netdev_state_change(dev); return 0; } tun->flags = (tun->flags & ~TUN_FEATURES) | (ifr->ifr_flags & TUN_FEATURES); - } - else { + + netdev_state_change(dev); + } else { char *name; unsigned long flags = 0; int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? @@ -2808,6 +2817,9 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) } else ret = -EINVAL; + if (ret >= 0) + netdev_state_change(tun->dev); + unlock: rtnl_unlock(); return ret; @@ -2848,6 +2860,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, unsigned int ifindex; int le; int ret; + bool do_notify = false; if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { @@ -2944,10 +2957,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, if (arg && !(tun->flags & IFF_PERSIST)) { tun->flags |= IFF_PERSIST; __module_get(THIS_MODULE); + do_notify = true; } if (!arg && (tun->flags & IFF_PERSIST)) { tun->flags &= ~IFF_PERSIST; module_put(THIS_MODULE); + do_notify = true; } tun_debug(KERN_INFO, tun, "persist %s\n", @@ -2962,6 +2977,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; } tun->owner = owner; + do_notify = true; tun_debug(KERN_INFO, tun, "owner set to %u\n", from_kuid(&init_user_ns, tun->owner)); break; @@ -2974,6 +2990,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; } tun->group = group; + do_notify = true; tun_debug(KERN_INFO, tun, "group set to %u\n", from_kgid(&init_user_ns, tun->group)); break; @@ -3133,6 +3150,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; } + if (do_notify) + netdev_state_change(tun->dev); + unlock: rtnl_unlock(); if (tun)