aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c70
1 files changed, 31 insertions, 39 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 11a0ba47b677..42b6c6319bc2 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
486{ 486{
487 struct tun_file *tfile = file->private_data; 487 struct tun_file *tfile = file->private_data;
488 struct tun_struct *tun = __tun_get(tfile); 488 struct tun_struct *tun = __tun_get(tfile);
489 struct sock *sk = tun->sk; 489 struct sock *sk;
490 unsigned int mask = 0; 490 unsigned int mask = 0;
491 491
492 if (!tun) 492 if (!tun)
493 return POLLERR; 493 return POLLERR;
494 494
495 sk = tun->sk;
496
495 DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name); 497 DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
496 498
497 poll_wait(file, &tun->socket.wait, wait); 499 poll_wait(file, &tun->socket.wait, wait);
@@ -1046,20 +1048,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1046 return err; 1048 return err;
1047} 1049}
1048 1050
1049static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) 1051static int tun_get_iff(struct net *net, struct tun_struct *tun,
1052 struct ifreq *ifr)
1050{ 1053{
1051 struct tun_struct *tun = tun_get(file);
1052
1053 if (!tun)
1054 return -EBADFD;
1055
1056 DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name); 1054 DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
1057 1055
1058 strcpy(ifr->ifr_name, tun->dev->name); 1056 strcpy(ifr->ifr_name, tun->dev->name);
1059 1057
1060 ifr->ifr_flags = tun_flags(tun); 1058 ifr->ifr_flags = tun_flags(tun);
1061 1059
1062 tun_put(tun);
1063 return 0; 1060 return 0;
1064} 1061}
1065 1062
@@ -1103,8 +1100,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
1103 return 0; 1100 return 0;
1104} 1101}
1105 1102
1106static int tun_chr_ioctl(struct inode *inode, struct file *file, 1103static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1107 unsigned int cmd, unsigned long arg) 1104 unsigned long arg)
1108{ 1105{
1109 struct tun_file *tfile = file->private_data; 1106 struct tun_file *tfile = file->private_data;
1110 struct tun_struct *tun; 1107 struct tun_struct *tun;
@@ -1126,34 +1123,32 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1126 (unsigned int __user*)argp); 1123 (unsigned int __user*)argp);
1127 } 1124 }
1128 1125
1126 rtnl_lock();
1127
1129 tun = __tun_get(tfile); 1128 tun = __tun_get(tfile);
1130 if (cmd == TUNSETIFF && !tun) { 1129 if (cmd == TUNSETIFF && !tun) {
1131 int err;
1132
1133 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 1130 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1134 1131
1135 rtnl_lock(); 1132 ret = tun_set_iff(tfile->net, file, &ifr);
1136 err = tun_set_iff(tfile->net, file, &ifr);
1137 rtnl_unlock();
1138 1133
1139 if (err) 1134 if (ret)
1140 return err; 1135 goto unlock;
1141 1136
1142 if (copy_to_user(argp, &ifr, sizeof(ifr))) 1137 if (copy_to_user(argp, &ifr, sizeof(ifr)))
1143 return -EFAULT; 1138 ret = -EFAULT;
1144 return 0; 1139 goto unlock;
1145 } 1140 }
1146 1141
1147 1142 ret = -EBADFD;
1148 if (!tun) 1143 if (!tun)
1149 return -EBADFD; 1144 goto unlock;
1150 1145
1151 DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); 1146 DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
1152 1147
1153 ret = 0; 1148 ret = 0;
1154 switch (cmd) { 1149 switch (cmd) {
1155 case TUNGETIFF: 1150 case TUNGETIFF:
1156 ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); 1151 ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
1157 if (ret) 1152 if (ret)
1158 break; 1153 break;
1159 1154
@@ -1199,7 +1194,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1199 1194
1200 case TUNSETLINK: 1195 case TUNSETLINK:
1201 /* Only allow setting the type when the interface is down */ 1196 /* Only allow setting the type when the interface is down */
1202 rtnl_lock();
1203 if (tun->dev->flags & IFF_UP) { 1197 if (tun->dev->flags & IFF_UP) {
1204 DBG(KERN_INFO "%s: Linktype set failed because interface is up\n", 1198 DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
1205 tun->dev->name); 1199 tun->dev->name);
@@ -1209,7 +1203,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1209 DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type); 1203 DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
1210 ret = 0; 1204 ret = 0;
1211 } 1205 }
1212 rtnl_unlock();
1213 break; 1206 break;
1214 1207
1215#ifdef TUN_DEBUG 1208#ifdef TUN_DEBUG
@@ -1218,9 +1211,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1218 break; 1211 break;
1219#endif 1212#endif
1220 case TUNSETOFFLOAD: 1213 case TUNSETOFFLOAD:
1221 rtnl_lock();
1222 ret = set_offload(tun->dev, arg); 1214 ret = set_offload(tun->dev, arg);
1223 rtnl_unlock();
1224 break; 1215 break;
1225 1216
1226 case TUNSETTXFILTER: 1217 case TUNSETTXFILTER:
@@ -1228,9 +1219,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1228 ret = -EINVAL; 1219 ret = -EINVAL;
1229 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) 1220 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
1230 break; 1221 break;
1231 rtnl_lock();
1232 ret = update_filter(&tun->txflt, (void __user *)arg); 1222 ret = update_filter(&tun->txflt, (void __user *)arg);
1233 rtnl_unlock();
1234 break; 1223 break;
1235 1224
1236 case SIOCGIFHWADDR: 1225 case SIOCGIFHWADDR:
@@ -1246,9 +1235,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1246 DBG(KERN_DEBUG "%s: set hw address: %pM\n", 1235 DBG(KERN_DEBUG "%s: set hw address: %pM\n",
1247 tun->dev->name, ifr.ifr_hwaddr.sa_data); 1236 tun->dev->name, ifr.ifr_hwaddr.sa_data);
1248 1237
1249 rtnl_lock();
1250 ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); 1238 ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
1251 rtnl_unlock();
1252 break; 1239 break;
1253 1240
1254 case TUNGETSNDBUF: 1241 case TUNGETSNDBUF:
@@ -1271,7 +1258,10 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1271 break; 1258 break;
1272 }; 1259 };
1273 1260
1274 tun_put(tun); 1261unlock:
1262 rtnl_unlock();
1263 if (tun)
1264 tun_put(tun);
1275 return ret; 1265 return ret;
1276} 1266}
1277 1267
@@ -1324,20 +1314,22 @@ static int tun_chr_close(struct inode *inode, struct file *file)
1324 struct tun_file *tfile = file->private_data; 1314 struct tun_file *tfile = file->private_data;
1325 struct tun_struct *tun; 1315 struct tun_struct *tun;
1326 1316
1327
1328 rtnl_lock();
1329 tun = __tun_get(tfile); 1317 tun = __tun_get(tfile);
1330 if (tun) { 1318 if (tun) {
1331 DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); 1319 struct net_device *dev = tun->dev;
1320
1321 DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
1332 1322
1333 __tun_detach(tun); 1323 __tun_detach(tun);
1334 1324
1335 /* If desireable, unregister the netdevice. */ 1325 /* If desireable, unregister the netdevice. */
1336 if (!(tun->flags & TUN_PERSIST)) 1326 if (!(tun->flags & TUN_PERSIST)) {
1337 unregister_netdevice(tun->dev); 1327 rtnl_lock();
1338 1328 if (dev->reg_state == NETREG_REGISTERED)
1329 unregister_netdevice(dev);
1330 rtnl_unlock();
1331 }
1339 } 1332 }
1340 rtnl_unlock();
1341 1333
1342 tun = tfile->tun; 1334 tun = tfile->tun;
1343 if (tun) 1335 if (tun)
@@ -1357,7 +1349,7 @@ static const struct file_operations tun_fops = {
1357 .write = do_sync_write, 1349 .write = do_sync_write,
1358 .aio_write = tun_chr_aio_write, 1350 .aio_write = tun_chr_aio_write,
1359 .poll = tun_chr_poll, 1351 .poll = tun_chr_poll,
1360 .ioctl = tun_chr_ioctl, 1352 .unlocked_ioctl = tun_chr_ioctl,
1361 .open = tun_chr_open, 1353 .open = tun_chr_open,
1362 .release = tun_chr_close, 1354 .release = tun_chr_close,
1363 .fasync = tun_chr_fasync 1355 .fasync = tun_chr_fasync