diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 07:55:01 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 07:55:01 -0800 |
commit | d7fc02c7bae7b1cf69269992cf880a43a350cdaa (patch) | |
tree | a43d56fa72913a1cc98a0bbebe054d08581b3a7c /drivers/net/tun.c | |
parent | ee1262dbc65ce0b6234a915d8432171e8d77f518 (diff) | |
parent | 28b4d5cc17c20786848cdc07b7ea237a309776bb (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1815 commits)
mac80211: fix reorder buffer release
iwmc3200wifi: Enable wimax core through module parameter
iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter
iwmc3200wifi: Coex table command does not expect a response
iwmc3200wifi: Update wiwi priority table
iwlwifi: driver version track kernel version
iwlwifi: indicate uCode type when fail dump error/event log
iwl3945: remove duplicated event logging code
b43: fix two warnings
ipw2100: fix rebooting hang with driver loaded
cfg80211: indent regulatory messages with spaces
iwmc3200wifi: fix NULL pointer dereference in pmkid update
mac80211: Fix TX status reporting for injected data frames
ath9k: enable 2GHz band only if the device supports it
airo: Fix integer overflow warning
rt2x00: Fix padding bug on L2PAD devices.
WE: Fix set events not propagated
b43legacy: avoid PPC fault during resume
b43: avoid PPC fault during resume
tcp: fix a timewait refcnt race
...
Fix up conflicts due to sysctl cleanups (dead sysctl_check code and
CTL_UNNUMBERED removed) in
kernel/sysctl_check.c
net/ipv4/sysctl_net_ipv4.c
net/ipv6/addrconf.c
net/sctp/sysctl.c
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 4fdfa2ae541..01e99f22210 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -44,7 +44,6 @@ #include <linux/kernel.h> #include <linux/major.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/poll.h> #include <linux/fcntl.h> #include <linux/init.h> @@ -54,6 +53,7 @@ #include <linux/miscdevice.h> #include <linux/ethtool.h> #include <linux/rtnetlink.h> +#include <linux/compat.h> #include <linux/if.h> #include <linux/if_arp.h> #include <linux/if_ether.h> @@ -1110,8 +1110,8 @@ static int set_offload(struct net_device *dev, unsigned long arg) return 0; } -static long tun_chr_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static long __tun_chr_ioctl(struct file *file, unsigned int cmd, + unsigned long arg, int ifreq_len) { struct tun_file *tfile = file->private_data; struct tun_struct *tun; @@ -1121,7 +1121,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, int ret; if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) - if (copy_from_user(&ifr, argp, sizeof ifr)) + if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; if (cmd == TUNGETFEATURES) { @@ -1144,7 +1144,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, if (ret) goto unlock; - if (copy_to_user(argp, &ifr, sizeof(ifr))) + if (copy_to_user(argp, &ifr, ifreq_len)) ret = -EFAULT; goto unlock; } @@ -1162,7 +1162,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (copy_to_user(argp, &ifr, sizeof(ifr))) + if (copy_to_user(argp, &ifr, ifreq_len)) ret = -EFAULT; break; @@ -1236,7 +1236,7 @@ static long tun_chr_ioctl(struct file *file, unsigned int cmd, /* Get hw addres */ memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); ifr.ifr_hwaddr.sa_family = tun->dev->type; - if (copy_to_user(argp, &ifr, sizeof ifr)) + if (copy_to_user(argp, &ifr, ifreq_len)) ret = -EFAULT; break; @@ -1275,6 +1275,41 @@ unlock: return ret; } +static long tun_chr_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return __tun_chr_ioctl(file, cmd, arg, sizeof (struct ifreq)); +} + +#ifdef CONFIG_COMPAT +static long tun_chr_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TUNSETIFF: + case TUNGETIFF: + case TUNSETTXFILTER: + case TUNGETSNDBUF: + case TUNSETSNDBUF: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + arg = (unsigned long)compat_ptr(arg); + break; + default: + arg = (compat_ulong_t)arg; + break; + } + + /* + * compat_ifreq is shorter than ifreq, so we must not access beyond + * the end of that structure. All fields that are used in this + * driver are compatible though, we don't need to convert the + * contents. + */ + return __tun_chr_ioctl(file, cmd, arg, sizeof(struct compat_ifreq)); +} +#endif /* CONFIG_COMPAT */ + static int tun_chr_fasync(int fd, struct file *file, int on) { struct tun_struct *tun = tun_get(file); @@ -1285,7 +1320,6 @@ static int tun_chr_fasync(int fd, struct file *file, int on) DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on); - lock_kernel(); if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) goto out; @@ -1298,7 +1332,6 @@ static int tun_chr_fasync(int fd, struct file *file, int on) tun->flags &= ~TUN_FASYNC; ret = 0; out: - unlock_kernel(); tun_put(tun); return ret; } @@ -1306,7 +1339,7 @@ out: static int tun_chr_open(struct inode *inode, struct file * file) { struct tun_file *tfile; - cycle_kernel_lock(); + DBG1(KERN_INFO "tunX: tun_chr_open\n"); tfile = kmalloc(sizeof(*tfile), GFP_KERNEL); @@ -1359,7 +1392,10 @@ static const struct file_operations tun_fops = { .write = do_sync_write, .aio_write = tun_chr_aio_write, .poll = tun_chr_poll, - .unlocked_ioctl = tun_chr_ioctl, + .unlocked_ioctl = tun_chr_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tun_chr_compat_ioctl, +#endif .open = tun_chr_open, .release = tun_chr_close, .fasync = tun_chr_fasync |