diff options
-rw-r--r-- | drivers/net/tun.c | 53 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 20 |
2 files changed, 46 insertions, 27 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9c59a82784dc..01e99f22210e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/miscdevice.h> | 53 | #include <linux/miscdevice.h> |
54 | #include <linux/ethtool.h> | 54 | #include <linux/ethtool.h> |
55 | #include <linux/rtnetlink.h> | 55 | #include <linux/rtnetlink.h> |
56 | #include <linux/compat.h> | ||
56 | #include <linux/if.h> | 57 | #include <linux/if.h> |
57 | #include <linux/if_arp.h> | 58 | #include <linux/if_arp.h> |
58 | #include <linux/if_ether.h> | 59 | #include <linux/if_ether.h> |
@@ -1109,8 +1110,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) | |||
1109 | return 0; | 1110 | return 0; |
1110 | } | 1111 | } |
1111 | 1112 | ||
1112 | static long tun_chr_ioctl(struct file *file, unsigned int cmd, | 1113 | static long __tun_chr_ioctl(struct file *file, unsigned int cmd, |
1113 | unsigned long arg) | 1114 | unsigned long arg, int ifreq_len) |
1114 | { | 1115 | { |
1115 | struct tun_file *tfile = file->private_data; | 1116 | struct tun_file *tfile = file->private_data; |
1116 | struct tun_struct *tun; | 1117 | struct tun_struct *tun; |
@@ -1120,7 +1121,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1120 | int ret; | 1121 | int ret; |
1121 | 1122 | ||
1122 | if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) | 1123 | if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) |
1123 | if (copy_from_user(&ifr, argp, sizeof ifr)) | 1124 | if (copy_from_user(&ifr, argp, ifreq_len)) |
1124 | return -EFAULT; | 1125 | return -EFAULT; |
1125 | 1126 | ||
1126 | if (cmd == TUNGETFEATURES) { | 1127 | if (cmd == TUNGETFEATURES) { |
@@ -1143,7 +1144,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1143 | if (ret) | 1144 | if (ret) |
1144 | goto unlock; | 1145 | goto unlock; |
1145 | 1146 | ||
1146 | if (copy_to_user(argp, &ifr, sizeof(ifr))) | 1147 | if (copy_to_user(argp, &ifr, ifreq_len)) |
1147 | ret = -EFAULT; | 1148 | ret = -EFAULT; |
1148 | goto unlock; | 1149 | goto unlock; |
1149 | } | 1150 | } |
@@ -1161,7 +1162,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1161 | if (ret) | 1162 | if (ret) |
1162 | break; | 1163 | break; |
1163 | 1164 | ||
1164 | if (copy_to_user(argp, &ifr, sizeof(ifr))) | 1165 | if (copy_to_user(argp, &ifr, ifreq_len)) |
1165 | ret = -EFAULT; | 1166 | ret = -EFAULT; |
1166 | break; | 1167 | break; |
1167 | 1168 | ||
@@ -1235,7 +1236,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1235 | /* Get hw addres */ | 1236 | /* Get hw addres */ |
1236 | 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); |
1237 | ifr.ifr_hwaddr.sa_family = tun->dev->type; | 1238 | ifr.ifr_hwaddr.sa_family = tun->dev->type; |
1238 | if (copy_to_user(argp, &ifr, sizeof ifr)) | 1239 | if (copy_to_user(argp, &ifr, ifreq_len)) |
1239 | ret = -EFAULT; | 1240 | ret = -EFAULT; |
1240 | break; | 1241 | break; |
1241 | 1242 | ||
@@ -1274,6 +1275,41 @@ unlock: | |||
1274 | return ret; | 1275 | return ret; |
1275 | } | 1276 | } |
1276 | 1277 | ||
1278 | static 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 | ||
1285 | static 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 | |||
1277 | static int tun_chr_fasync(int fd, struct file *file, int on) | 1313 | static int tun_chr_fasync(int fd, struct file *file, int on) |
1278 | { | 1314 | { |
1279 | struct tun_struct *tun = tun_get(file); | 1315 | struct tun_struct *tun = tun_get(file); |
@@ -1356,7 +1392,10 @@ static const struct file_operations tun_fops = { | |||
1356 | .write = do_sync_write, | 1392 | .write = do_sync_write, |
1357 | .aio_write = tun_chr_aio_write, | 1393 | .aio_write = tun_chr_aio_write, |
1358 | .poll = tun_chr_poll, | 1394 | .poll = tun_chr_poll, |
1359 | .unlocked_ioctl = tun_chr_ioctl, | 1395 | .unlocked_ioctl = tun_chr_ioctl, |
1396 | #ifdef CONFIG_COMPAT | ||
1397 | .compat_ioctl = tun_chr_compat_ioctl, | ||
1398 | #endif | ||
1360 | .open = tun_chr_open, | 1399 | .open = tun_chr_open, |
1361 | .release = tun_chr_close, | 1400 | .release = tun_chr_close, |
1362 | .fasync = tun_chr_fasync | 1401 | .fasync = tun_chr_fasync |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f91fd51b32e3..c562e9a4da70 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -539,12 +539,6 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
539 | set_fs (old_fs); | 539 | set_fs (old_fs); |
540 | if (!err) { | 540 | if (!err) { |
541 | switch (cmd) { | 541 | switch (cmd) { |
542 | /* TUNSETIFF is defined as _IOW, it should be _IORW | ||
543 | * as the data is copied back to user space, but that | ||
544 | * cannot be fixed without breaking all existing apps. | ||
545 | */ | ||
546 | case TUNSETIFF: | ||
547 | case TUNGETIFF: | ||
548 | case SIOCGIFFLAGS: | 542 | case SIOCGIFFLAGS: |
549 | case SIOCGIFMETRIC: | 543 | case SIOCGIFMETRIC: |
550 | case SIOCGIFMTU: | 544 | case SIOCGIFMTU: |
@@ -1979,18 +1973,6 @@ COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) | |||
1979 | COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) | 1973 | COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) |
1980 | COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) | 1974 | COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) |
1981 | #endif | 1975 | #endif |
1982 | /* Big T */ | ||
1983 | COMPATIBLE_IOCTL(TUNSETNOCSUM) | ||
1984 | COMPATIBLE_IOCTL(TUNSETDEBUG) | ||
1985 | COMPATIBLE_IOCTL(TUNSETPERSIST) | ||
1986 | COMPATIBLE_IOCTL(TUNSETOWNER) | ||
1987 | COMPATIBLE_IOCTL(TUNSETLINK) | ||
1988 | COMPATIBLE_IOCTL(TUNSETGROUP) | ||
1989 | COMPATIBLE_IOCTL(TUNGETFEATURES) | ||
1990 | COMPATIBLE_IOCTL(TUNSETOFFLOAD) | ||
1991 | COMPATIBLE_IOCTL(TUNSETTXFILTER) | ||
1992 | COMPATIBLE_IOCTL(TUNGETSNDBUF) | ||
1993 | COMPATIBLE_IOCTL(TUNSETSNDBUF) | ||
1994 | /* Big V */ | 1976 | /* Big V */ |
1995 | COMPATIBLE_IOCTL(VT_SETMODE) | 1977 | COMPATIBLE_IOCTL(VT_SETMODE) |
1996 | COMPATIBLE_IOCTL(VT_GETMODE) | 1978 | COMPATIBLE_IOCTL(VT_GETMODE) |
@@ -2571,8 +2553,6 @@ HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) | |||
2571 | HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) | 2553 | HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) |
2572 | HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) | 2554 | HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) |
2573 | HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) | 2555 | HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) |
2574 | HANDLE_IOCTL(TUNSETIFF, dev_ifsioc) | ||
2575 | HANDLE_IOCTL(TUNGETIFF, dev_ifsioc) | ||
2576 | HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) | 2556 | HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) |
2577 | HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) | 2557 | HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) |
2578 | HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) | 2558 | HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) |