diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2018-04-10 10:28:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-11 14:48:05 -0400 |
commit | 83c1f36f9880814b24cdf6c2f91f66f61db65326 (patch) | |
tree | f80ca21c633842383f1f9950a821e4ce5bd7d26a | |
parent | 9fffc5c6dd7dafb2e021dbbe9a30be2566a6949a (diff) |
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 <thaller@redhat.com>
Fixes: 1ec010e70593 ("tun: export flags, uid, gid, queue information over netlink")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tun.c | 24 |
1 files 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) | |||
743 | 743 | ||
744 | static void tun_detach(struct tun_file *tfile, bool clean) | 744 | static void tun_detach(struct tun_file *tfile, bool clean) |
745 | { | 745 | { |
746 | struct tun_struct *tun; | ||
747 | struct net_device *dev; | ||
748 | |||
746 | rtnl_lock(); | 749 | rtnl_lock(); |
750 | tun = rtnl_dereference(tfile->tun); | ||
751 | dev = tun ? tun->dev : NULL; | ||
747 | __tun_detach(tfile, clean); | 752 | __tun_detach(tfile, clean); |
753 | if (dev) | ||
754 | netdev_state_change(dev); | ||
748 | rtnl_unlock(); | 755 | rtnl_unlock(); |
749 | } | 756 | } |
750 | 757 | ||
@@ -2562,13 +2569,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
2562 | /* One or more queue has already been attached, no need | 2569 | /* One or more queue has already been attached, no need |
2563 | * to initialize the device again. | 2570 | * to initialize the device again. |
2564 | */ | 2571 | */ |
2572 | netdev_state_change(dev); | ||
2565 | return 0; | 2573 | return 0; |
2566 | } | 2574 | } |
2567 | 2575 | ||
2568 | tun->flags = (tun->flags & ~TUN_FEATURES) | | 2576 | tun->flags = (tun->flags & ~TUN_FEATURES) | |
2569 | (ifr->ifr_flags & TUN_FEATURES); | 2577 | (ifr->ifr_flags & TUN_FEATURES); |
2570 | } | 2578 | |
2571 | else { | 2579 | netdev_state_change(dev); |
2580 | } else { | ||
2572 | char *name; | 2581 | char *name; |
2573 | unsigned long flags = 0; | 2582 | unsigned long flags = 0; |
2574 | int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? | 2583 | int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? |
@@ -2808,6 +2817,9 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) | |||
2808 | } else | 2817 | } else |
2809 | ret = -EINVAL; | 2818 | ret = -EINVAL; |
2810 | 2819 | ||
2820 | if (ret >= 0) | ||
2821 | netdev_state_change(tun->dev); | ||
2822 | |||
2811 | unlock: | 2823 | unlock: |
2812 | rtnl_unlock(); | 2824 | rtnl_unlock(); |
2813 | return ret; | 2825 | return ret; |
@@ -2848,6 +2860,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
2848 | unsigned int ifindex; | 2860 | unsigned int ifindex; |
2849 | int le; | 2861 | int le; |
2850 | int ret; | 2862 | int ret; |
2863 | bool do_notify = false; | ||
2851 | 2864 | ||
2852 | if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || | 2865 | if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || |
2853 | (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { | 2866 | (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { |
@@ -2944,10 +2957,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
2944 | if (arg && !(tun->flags & IFF_PERSIST)) { | 2957 | if (arg && !(tun->flags & IFF_PERSIST)) { |
2945 | tun->flags |= IFF_PERSIST; | 2958 | tun->flags |= IFF_PERSIST; |
2946 | __module_get(THIS_MODULE); | 2959 | __module_get(THIS_MODULE); |
2960 | do_notify = true; | ||
2947 | } | 2961 | } |
2948 | if (!arg && (tun->flags & IFF_PERSIST)) { | 2962 | if (!arg && (tun->flags & IFF_PERSIST)) { |
2949 | tun->flags &= ~IFF_PERSIST; | 2963 | tun->flags &= ~IFF_PERSIST; |
2950 | module_put(THIS_MODULE); | 2964 | module_put(THIS_MODULE); |
2965 | do_notify = true; | ||
2951 | } | 2966 | } |
2952 | 2967 | ||
2953 | tun_debug(KERN_INFO, tun, "persist %s\n", | 2968 | tun_debug(KERN_INFO, tun, "persist %s\n", |
@@ -2962,6 +2977,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
2962 | break; | 2977 | break; |
2963 | } | 2978 | } |
2964 | tun->owner = owner; | 2979 | tun->owner = owner; |
2980 | do_notify = true; | ||
2965 | tun_debug(KERN_INFO, tun, "owner set to %u\n", | 2981 | tun_debug(KERN_INFO, tun, "owner set to %u\n", |
2966 | from_kuid(&init_user_ns, tun->owner)); | 2982 | from_kuid(&init_user_ns, tun->owner)); |
2967 | break; | 2983 | break; |
@@ -2974,6 +2990,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
2974 | break; | 2990 | break; |
2975 | } | 2991 | } |
2976 | tun->group = group; | 2992 | tun->group = group; |
2993 | do_notify = true; | ||
2977 | tun_debug(KERN_INFO, tun, "group set to %u\n", | 2994 | tun_debug(KERN_INFO, tun, "group set to %u\n", |
2978 | from_kgid(&init_user_ns, tun->group)); | 2995 | from_kgid(&init_user_ns, tun->group)); |
2979 | break; | 2996 | break; |
@@ -3133,6 +3150,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
3133 | break; | 3150 | break; |
3134 | } | 3151 | } |
3135 | 3152 | ||
3153 | if (do_notify) | ||
3154 | netdev_state_change(tun->dev); | ||
3155 | |||
3136 | unlock: | 3156 | unlock: |
3137 | rtnl_unlock(); | 3157 | rtnl_unlock(); |
3138 | if (tun) | 3158 | if (tun) |