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.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4fdfa2ae5418..01e99f22210e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -44,7 +44,6 @@
44#include <linux/kernel.h> 44#include <linux/kernel.h>
45#include <linux/major.h> 45#include <linux/major.h>
46#include <linux/slab.h> 46#include <linux/slab.h>
47#include <linux/smp_lock.h>
48#include <linux/poll.h> 47#include <linux/poll.h>
49#include <linux/fcntl.h> 48#include <linux/fcntl.h>
50#include <linux/init.h> 49#include <linux/init.h>
@@ -54,6 +53,7 @@
54#include <linux/miscdevice.h> 53#include <linux/miscdevice.h>
55#include <linux/ethtool.h> 54#include <linux/ethtool.h>
56#include <linux/rtnetlink.h> 55#include <linux/rtnetlink.h>
56#include <linux/compat.h>
57#include <linux/if.h> 57#include <linux/if.h>
58#include <linux/if_arp.h> 58#include <linux/if_arp.h>
59#include <linux/if_ether.h> 59#include <linux/if_ether.h>
@@ -1110,8 +1110,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
1110 return 0; 1110 return 0;
1111} 1111}
1112 1112
1113static long tun_chr_ioctl(struct file *file, unsigned int cmd, 1113static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1114 unsigned long arg) 1114 unsigned long arg, int ifreq_len)
1115{ 1115{
1116 struct tun_file *tfile = file->private_data; 1116 struct tun_file *tfile = file->private_data;
1117 struct tun_struct *tun; 1117 struct tun_struct *tun;
@@ -1121,7 +1121,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1121 int ret; 1121 int ret;
1122 1122
1123 if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) 1123 if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
1124 if (copy_from_user(&ifr, argp, sizeof ifr)) 1124 if (copy_from_user(&ifr, argp, ifreq_len))
1125 return -EFAULT; 1125 return -EFAULT;
1126 1126
1127 if (cmd == TUNGETFEATURES) { 1127 if (cmd == TUNGETFEATURES) {
@@ -1144,7 +1144,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1144 if (ret) 1144 if (ret)
1145 goto unlock; 1145 goto unlock;
1146 1146
1147 if (copy_to_user(argp, &ifr, sizeof(ifr))) 1147 if (copy_to_user(argp, &ifr, ifreq_len))
1148 ret = -EFAULT; 1148 ret = -EFAULT;
1149 goto unlock; 1149 goto unlock;
1150 } 1150 }
@@ -1162,7 +1162,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1162 if (ret) 1162 if (ret)
1163 break; 1163 break;
1164 1164
1165 if (copy_to_user(argp, &ifr, sizeof(ifr))) 1165 if (copy_to_user(argp, &ifr, ifreq_len))
1166 ret = -EFAULT; 1166 ret = -EFAULT;
1167 break; 1167 break;
1168 1168
@@ -1236,7 +1236,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd,
1236 /* Get hw addres */ 1236 /* Get hw addres */
1237 memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); 1237 memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
1238 ifr.ifr_hwaddr.sa_family = tun->dev->type; 1238 ifr.ifr_hwaddr.sa_family = tun->dev->type;
1239 if (copy_to_user(argp, &ifr, sizeof ifr)) 1239 if (copy_to_user(argp, &ifr, ifreq_len))
1240 ret = -EFAULT; 1240 ret = -EFAULT;
1241 break; 1241 break;
1242 1242
@@ -1275,6 +1275,41 @@ unlock:
1275 return ret; 1275 return ret;
1276} 1276}
1277 1277
1278static long tun_chr_ioctl(struct file *file,
1279 unsigned int cmd, unsigned long arg)
1280{
1281 return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq));
1282}
1283
1284#ifdef CONFIG_COMPAT
1285static long tun_chr_compat_ioctl(struct file *file,
1286 unsigned int cmd, unsigned long arg)
1287{
1288 switch (cmd) {
1289 case TUNSETIFF:
1290 case TUNGETIFF:
1291 case TUNSETTXFILTER:
1292 case TUNGETSNDBUF:
1293 case TUNSETSNDBUF:
1294 case SIOCGIFHWADDR:
1295 case SIOCSIFHWADDR:
1296 arg = (unsigned long)compat_ptr(arg);
1297 break;
1298 default:
1299 arg = (compat_ulong_t)arg;
1300 break;
1301 }
1302
1303 /*
1304 * compat_ifreq is shorter than ifreq, so we must not access beyond
1305 * the end of that structure. All fields that are used in this
1306 * driver are compatible though, we don't need to convert the
1307 * contents.
1308 */
1309 return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq));
1310}
1311#endif /* CONFIG_COMPAT */
1312
1278static int tun_chr_fasync(int fd, struct file *file, int on) 1313static int tun_chr_fasync(int fd, struct file *file, int on)
1279{ 1314{
1280 struct tun_struct *tun = tun_get(file); 1315 struct tun_struct *tun = tun_get(file);
@@ -1285,7 +1320,6 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
1285 1320
1286 DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on); 1321 DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
1287 1322
1288 lock_kernel();
1289 if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) 1323 if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
1290 goto out; 1324 goto out;
1291 1325
@@ -1298,7 +1332,6 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
1298 tun->flags &= ~TUN_FASYNC; 1332 tun->flags &= ~TUN_FASYNC;
1299 ret = 0; 1333 ret = 0;
1300out: 1334out:
1301 unlock_kernel();
1302 tun_put(tun); 1335 tun_put(tun);
1303 return ret; 1336 return ret;
1304} 1337}
@@ -1306,7 +1339,7 @@ out:
1306static int tun_chr_open(struct inode *inode, struct file * file) 1339static int tun_chr_open(struct inode *inode, struct file * file)
1307{ 1340{
1308 struct tun_file *tfile; 1341 struct tun_file *tfile;
1309 cycle_kernel_lock(); 1342
1310 DBG1(KERN_INFO "tunX: tun_chr_open\n"); 1343 DBG1(KERN_INFO "tunX: tun_chr_open\n");
1311 1344
1312 tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); 1345 tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
@@ -1359,7 +1392,10 @@ static const struct file_operations tun_fops = {
1359 .write = do_sync_write, 1392 .write = do_sync_write,
1360 .aio_write = tun_chr_aio_write, 1393 .aio_write = tun_chr_aio_write,
1361 .poll = tun_chr_poll, 1394 .poll = tun_chr_poll,
1362 .unlocked_ioctl = tun_chr_ioctl, 1395 .unlocked_ioctl = tun_chr_ioctl,
1396#ifdef CONFIG_COMPAT
1397 .compat_ioctl = tun_chr_compat_ioctl,
1398#endif
1363 .open = tun_chr_open, 1399 .open = tun_chr_open,
1364 .release = tun_chr_close, 1400 .release = tun_chr_close,
1365 .fasync = tun_chr_fasync 1401 .fasync = tun_chr_fasync