diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tun.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 42b6c6319bc2..87214a257d2a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -130,17 +130,10 @@ static inline struct tun_sock *tun_sk(struct sock *sk) | |||
130 | static int tun_attach(struct tun_struct *tun, struct file *file) | 130 | static int tun_attach(struct tun_struct *tun, struct file *file) |
131 | { | 131 | { |
132 | struct tun_file *tfile = file->private_data; | 132 | struct tun_file *tfile = file->private_data; |
133 | const struct cred *cred = current_cred(); | ||
134 | int err; | 133 | int err; |
135 | 134 | ||
136 | ASSERT_RTNL(); | 135 | ASSERT_RTNL(); |
137 | 136 | ||
138 | /* Check permissions */ | ||
139 | if (((tun->owner != -1 && cred->euid != tun->owner) || | ||
140 | (tun->group != -1 && !in_egroup_p(tun->group))) && | ||
141 | !capable(CAP_NET_ADMIN)) | ||
142 | return -EPERM; | ||
143 | |||
144 | netif_tx_lock_bh(tun->dev); | 137 | netif_tx_lock_bh(tun->dev); |
145 | 138 | ||
146 | err = -EINVAL; | 139 | err = -EINVAL; |
@@ -926,6 +919,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
926 | 919 | ||
927 | dev = __dev_get_by_name(net, ifr->ifr_name); | 920 | dev = __dev_get_by_name(net, ifr->ifr_name); |
928 | if (dev) { | 921 | if (dev) { |
922 | const struct cred *cred = current_cred(); | ||
923 | |||
929 | if (ifr->ifr_flags & IFF_TUN_EXCL) | 924 | if (ifr->ifr_flags & IFF_TUN_EXCL) |
930 | return -EBUSY; | 925 | return -EBUSY; |
931 | if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) | 926 | if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops) |
@@ -935,6 +930,14 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
935 | else | 930 | else |
936 | return -EINVAL; | 931 | return -EINVAL; |
937 | 932 | ||
933 | if (((tun->owner != -1 && cred->euid != tun->owner) || | ||
934 | (tun->group != -1 && !in_egroup_p(tun->group))) && | ||
935 | !capable(CAP_NET_ADMIN)) | ||
936 | return -EPERM; | ||
937 | err = security_tun_dev_attach(tun->sk); | ||
938 | if (err < 0) | ||
939 | return err; | ||
940 | |||
938 | err = tun_attach(tun, file); | 941 | err = tun_attach(tun, file); |
939 | if (err < 0) | 942 | if (err < 0) |
940 | return err; | 943 | return err; |
@@ -947,6 +950,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
947 | 950 | ||
948 | if (!capable(CAP_NET_ADMIN)) | 951 | if (!capable(CAP_NET_ADMIN)) |
949 | return -EPERM; | 952 | return -EPERM; |
953 | err = security_tun_dev_create(); | ||
954 | if (err < 0) | ||
955 | return err; | ||
950 | 956 | ||
951 | /* Set dev type */ | 957 | /* Set dev type */ |
952 | if (ifr->ifr_flags & IFF_TUN) { | 958 | if (ifr->ifr_flags & IFF_TUN) { |
@@ -989,6 +995,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
989 | tun->sk = sk; | 995 | tun->sk = sk; |
990 | container_of(sk, struct tun_sock, sk)->tun = tun; | 996 | container_of(sk, struct tun_sock, sk)->tun = tun; |
991 | 997 | ||
998 | security_tun_dev_post_create(sk); | ||
999 | |||
992 | tun_net_init(dev); | 1000 | tun_net_init(dev); |
993 | 1001 | ||
994 | if (strchr(dev->name, '%')) { | 1002 | if (strchr(dev->name, '%')) { |