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.c50
1 files changed, 19 insertions, 31 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a998b6a9c245..2533f5cf2e4b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1052,20 +1052,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1052 return err; 1052 return err;
1053} 1053}
1054 1054
1055static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) 1055static int tun_get_iff(struct net *net, struct tun_struct *tun,
1056 struct ifreq *ifr)
1056{ 1057{
1057 struct tun_struct *tun = tun_get(file);
1058
1059 if (!tun)
1060 return -EBADFD;
1061
1062 DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name); 1058 DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
1063 1059
1064 strcpy(ifr->ifr_name, tun->dev->name); 1060 strcpy(ifr->ifr_name, tun->dev->name);
1065 1061
1066 ifr->ifr_flags = tun_flags(tun); 1062 ifr->ifr_flags = tun_flags(tun);
1067 1063
1068 tun_put(tun);
1069 return 0; 1064 return 0;
1070} 1065}
1071 1066
@@ -1115,8 +1110,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
1115 return 0; 1110 return 0;
1116} 1111}
1117 1112
1118static int tun_chr_ioctl(struct inode *inode, struct file *file, 1113static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1119 unsigned int cmd, unsigned long arg) 1114 unsigned long arg)
1120{ 1115{
1121 struct tun_file *tfile = file->private_data; 1116 struct tun_file *tfile = file->private_data;
1122 struct tun_struct *tun; 1117 struct tun_struct *tun;
@@ -1138,34 +1133,32 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1138 (unsigned int __user*)argp); 1133 (unsigned int __user*)argp);
1139 } 1134 }
1140 1135
1136 rtnl_lock();
1137
1141 tun = __tun_get(tfile); 1138 tun = __tun_get(tfile);
1142 if (cmd == TUNSETIFF && !tun) { 1139 if (cmd == TUNSETIFF && !tun) {
1143 int err;
1144
1145 ifr.ifr_name[IFNAMSIZ-1] = '\0'; 1140 ifr.ifr_name[IFNAMSIZ-1] = '\0';
1146 1141
1147 rtnl_lock(); 1142 ret = tun_set_iff(tfile->net, file, &ifr);
1148 err = tun_set_iff(tfile->net, file, &ifr);
1149 rtnl_unlock();
1150 1143
1151 if (err) 1144 if (ret)
1152 return err; 1145 goto unlock;
1153 1146
1154 if (copy_to_user(argp, &ifr, sizeof(ifr))) 1147 if (copy_to_user(argp, &ifr, sizeof(ifr)))
1155 return -EFAULT; 1148 ret = -EFAULT;
1156 return 0; 1149 goto unlock;
1157 } 1150 }
1158 1151
1159 1152 ret = -EBADFD;
1160 if (!tun) 1153 if (!tun)
1161 return -EBADFD; 1154 goto unlock;
1162 1155
1163 DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); 1156 DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
1164 1157
1165 ret = 0; 1158 ret = 0;
1166 switch (cmd) { 1159 switch (cmd) {
1167 case TUNGETIFF: 1160 case TUNGETIFF:
1168 ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); 1161 ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
1169 if (ret) 1162 if (ret)
1170 break; 1163 break;
1171 1164
@@ -1211,7 +1204,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1211 1204
1212 case TUNSETLINK: 1205 case TUNSETLINK:
1213 /* Only allow setting the type when the interface is down */ 1206 /* Only allow setting the type when the interface is down */
1214 rtnl_lock();
1215 if (tun->dev->flags & IFF_UP) { 1207 if (tun->dev->flags & IFF_UP) {
1216 DBG(KERN_INFO "%s: Linktype set failed because interface is up\n", 1208 DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
1217 tun->dev->name); 1209 tun->dev->name);
@@ -1221,7 +1213,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1221 DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type); 1213 DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
1222 ret = 0; 1214 ret = 0;
1223 } 1215 }
1224 rtnl_unlock();
1225 break; 1216 break;
1226 1217
1227#ifdef TUN_DEBUG 1218#ifdef TUN_DEBUG
@@ -1230,9 +1221,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1230 break; 1221 break;
1231#endif 1222#endif
1232 case TUNSETOFFLOAD: 1223 case TUNSETOFFLOAD:
1233 rtnl_lock();
1234 ret = set_offload(tun->dev, arg); 1224 ret = set_offload(tun->dev, arg);
1235 rtnl_unlock();
1236 break; 1225 break;
1237 1226
1238 case TUNSETTXFILTER: 1227 case TUNSETTXFILTER:
@@ -1240,9 +1229,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1240 ret = -EINVAL; 1229 ret = -EINVAL;
1241 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) 1230 if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
1242 break; 1231 break;
1243 rtnl_lock();
1244 ret = update_filter(&tun->txflt, (void __user *)arg); 1232 ret = update_filter(&tun->txflt, (void __user *)arg);
1245 rtnl_unlock();
1246 break; 1233 break;
1247 1234
1248 case SIOCGIFHWADDR: 1235 case SIOCGIFHWADDR:
@@ -1258,9 +1245,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1258 DBG(KERN_DEBUG "%s: set hw address: %pM\n", 1245 DBG(KERN_DEBUG "%s: set hw address: %pM\n",
1259 tun->dev->name, ifr.ifr_hwaddr.sa_data); 1246 tun->dev->name, ifr.ifr_hwaddr.sa_data);
1260 1247
1261 rtnl_lock();
1262 ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); 1248 ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
1263 rtnl_unlock();
1264 break; 1249 break;
1265 1250
1266 case TUNGETSNDBUF: 1251 case TUNGETSNDBUF:
@@ -1283,7 +1268,10 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
1283 break; 1268 break;
1284 }; 1269 };
1285 1270
1286 tun_put(tun); 1271unlock:
1272 rtnl_unlock();
1273 if (tun)
1274 tun_put(tun);
1287 return ret; 1275 return ret;
1288} 1276}
1289 1277
@@ -1371,7 +1359,7 @@ static const struct file_operations tun_fops = {
1371 .write = do_sync_write, 1359 .write = do_sync_write,
1372 .aio_write = tun_chr_aio_write, 1360 .aio_write = tun_chr_aio_write,
1373 .poll = tun_chr_poll, 1361 .poll = tun_chr_poll,
1374 .ioctl = tun_chr_ioctl, 1362 .unlocked_ioctl = tun_chr_ioctl,
1375 .open = tun_chr_open, 1363 .open = tun_chr_open,
1376 .release = tun_chr_close, 1364 .release = tun_chr_close,
1377 .fasync = tun_chr_fasync 1365 .fasync = tun_chr_fasync