mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	dev_ioctl(): move copyin/copyout to callers
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									6a88fbe725
								
							
						
					
					
						commit
						44c02a2c3d
					
				
					 3 changed files with 71 additions and 108 deletions
				
			
		| 
						 | 
					@ -3315,7 +3315,8 @@ int netdev_rx_handler_register(struct net_device *dev,
 | 
				
			||||||
void netdev_rx_handler_unregister(struct net_device *dev);
 | 
					void netdev_rx_handler_unregister(struct net_device *dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool dev_valid_name(const char *name);
 | 
					bool dev_valid_name(const char *name);
 | 
				
			||||||
int dev_ioctl(struct net *net, unsigned int cmd, void __user *);
 | 
					int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
 | 
				
			||||||
 | 
							bool *need_copyout);
 | 
				
			||||||
int dev_ifconf(struct net *net, struct ifconf *, int);
 | 
					int dev_ifconf(struct net *net, struct ifconf *, int);
 | 
				
			||||||
int dev_ethtool(struct net *net, struct ifreq *);
 | 
					int dev_ethtool(struct net *net, struct ifreq *);
 | 
				
			||||||
unsigned int dev_get_flags(const struct net_device *);
 | 
					unsigned int dev_get_flags(const struct net_device *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,26 +18,10 @@
 | 
				
			||||||
 *	match.  --pb
 | 
					 *	match.  --pb
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_ifname(struct net *net, struct ifreq __user *arg)
 | 
					static int dev_ifname(struct net *net, struct ifreq *ifr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ifreq ifr;
 | 
						ifr->ifr_name[IFNAMSIZ-1] = 0;
 | 
				
			||||||
	int error;
 | 
						return netdev_get_name(net, ifr->ifr_name, ifr->ifr_ifindex);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 *	Fetch the caller's info block.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	ifr.ifr_name[IFNAMSIZ-1] = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex);
 | 
					 | 
				
			||||||
	if (error)
 | 
					 | 
				
			||||||
		return error;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static gifconf_func_t *gifconf_list[NPROTO];
 | 
					static gifconf_func_t *gifconf_list[NPROTO];
 | 
				
			||||||
| 
						 | 
					@ -402,24 +386,24 @@ EXPORT_SYMBOL(dev_load);
 | 
				
			||||||
 *	positive or a negative errno code on error.
 | 
					 *	positive or a negative errno code on error.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 | 
					int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ifreq ifr;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	char *colon;
 | 
						char *colon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (need_copyout)
 | 
				
			||||||
 | 
							*need_copyout = true;
 | 
				
			||||||
	if (cmd == SIOCGIFNAME)
 | 
						if (cmd == SIOCGIFNAME)
 | 
				
			||||||
		return dev_ifname(net, (struct ifreq __user *)arg);
 | 
							return dev_ifname(net, ifr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 | 
						ifr->ifr_name[IFNAMSIZ-1] = 0;
 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ifr.ifr_name[IFNAMSIZ-1] = 0;
 | 
						colon = strchr(ifr->ifr_name, ':');
 | 
				
			||||||
 | 
					 | 
				
			||||||
	colon = strchr(ifr.ifr_name, ':');
 | 
					 | 
				
			||||||
	if (colon)
 | 
						if (colon)
 | 
				
			||||||
		*colon = 0;
 | 
							*colon = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_load(net, ifr->ifr_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 *	See which interface the caller is talking about.
 | 
						 *	See which interface the caller is talking about.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -439,31 +423,19 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 | 
				
			||||||
	case SIOCGIFMAP:
 | 
						case SIOCGIFMAP:
 | 
				
			||||||
	case SIOCGIFINDEX:
 | 
						case SIOCGIFINDEX:
 | 
				
			||||||
	case SIOCGIFTXQLEN:
 | 
						case SIOCGIFTXQLEN:
 | 
				
			||||||
		dev_load(net, ifr.ifr_name);
 | 
					 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
		ret = dev_ifsioc_locked(net, &ifr, cmd);
 | 
							ret = dev_ifsioc_locked(net, ifr, cmd);
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
		if (!ret) {
 | 
							if (colon)
 | 
				
			||||||
			if (colon)
 | 
								*colon = ':';
 | 
				
			||||||
				*colon = ':';
 | 
					 | 
				
			||||||
			if (copy_to_user(arg, &ifr,
 | 
					 | 
				
			||||||
					 sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
				ret = -EFAULT;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SIOCETHTOOL:
 | 
						case SIOCETHTOOL:
 | 
				
			||||||
		dev_load(net, ifr.ifr_name);
 | 
					 | 
				
			||||||
		rtnl_lock();
 | 
							rtnl_lock();
 | 
				
			||||||
		ret = dev_ethtool(net, &ifr);
 | 
							ret = dev_ethtool(net, ifr);
 | 
				
			||||||
		rtnl_unlock();
 | 
							rtnl_unlock();
 | 
				
			||||||
		if (!ret) {
 | 
							if (colon)
 | 
				
			||||||
			if (colon)
 | 
								*colon = ':';
 | 
				
			||||||
				*colon = ':';
 | 
					 | 
				
			||||||
			if (copy_to_user(arg, &ifr,
 | 
					 | 
				
			||||||
					 sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
				ret = -EFAULT;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -477,17 +449,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 | 
				
			||||||
	case SIOCSIFNAME:
 | 
						case SIOCSIFNAME:
 | 
				
			||||||
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 | 
							if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 | 
				
			||||||
			return -EPERM;
 | 
								return -EPERM;
 | 
				
			||||||
		dev_load(net, ifr.ifr_name);
 | 
					 | 
				
			||||||
		rtnl_lock();
 | 
							rtnl_lock();
 | 
				
			||||||
		ret = dev_ifsioc(net, &ifr, cmd);
 | 
							ret = dev_ifsioc(net, ifr, cmd);
 | 
				
			||||||
		rtnl_unlock();
 | 
							rtnl_unlock();
 | 
				
			||||||
		if (!ret) {
 | 
							if (colon)
 | 
				
			||||||
			if (colon)
 | 
								*colon = ':';
 | 
				
			||||||
				*colon = ':';
 | 
					 | 
				
			||||||
			if (copy_to_user(arg, &ifr,
 | 
					 | 
				
			||||||
					 sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
				ret = -EFAULT;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -528,10 +494,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 | 
				
			||||||
		/* fall through */
 | 
							/* fall through */
 | 
				
			||||||
	case SIOCBONDSLAVEINFOQUERY:
 | 
						case SIOCBONDSLAVEINFOQUERY:
 | 
				
			||||||
	case SIOCBONDINFOQUERY:
 | 
						case SIOCBONDINFOQUERY:
 | 
				
			||||||
		dev_load(net, ifr.ifr_name);
 | 
					 | 
				
			||||||
		rtnl_lock();
 | 
							rtnl_lock();
 | 
				
			||||||
		ret = dev_ifsioc(net, &ifr, cmd);
 | 
							ret = dev_ifsioc(net, ifr, cmd);
 | 
				
			||||||
		rtnl_unlock();
 | 
							rtnl_unlock();
 | 
				
			||||||
 | 
							if (need_copyout)
 | 
				
			||||||
 | 
								*need_copyout = false;
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case SIOCGIFMEM:
 | 
						case SIOCGIFMEM:
 | 
				
			||||||
| 
						 | 
					@ -551,13 +518,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 | 
				
			||||||
		    cmd == SIOCGHWTSTAMP ||
 | 
							    cmd == SIOCGHWTSTAMP ||
 | 
				
			||||||
		    (cmd >= SIOCDEVPRIVATE &&
 | 
							    (cmd >= SIOCDEVPRIVATE &&
 | 
				
			||||||
		     cmd <= SIOCDEVPRIVATE + 15)) {
 | 
							     cmd <= SIOCDEVPRIVATE + 15)) {
 | 
				
			||||||
			dev_load(net, ifr.ifr_name);
 | 
					 | 
				
			||||||
			rtnl_lock();
 | 
								rtnl_lock();
 | 
				
			||||||
			ret = dev_ifsioc(net, &ifr, cmd);
 | 
								ret = dev_ifsioc(net, ifr, cmd);
 | 
				
			||||||
			rtnl_unlock();
 | 
								rtnl_unlock();
 | 
				
			||||||
			if (!ret && copy_to_user(arg, &ifr,
 | 
					 | 
				
			||||||
						 sizeof(struct ifreq)))
 | 
					 | 
				
			||||||
				ret = -EFAULT;
 | 
					 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return -ENOTTY;
 | 
							return -ENOTTY;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										91
									
								
								net/socket.c
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								net/socket.c
									
									
									
									
									
								
							| 
						 | 
					@ -973,10 +973,17 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
 | 
				
			||||||
		rtnl_unlock();
 | 
							rtnl_unlock();
 | 
				
			||||||
		if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
 | 
							if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
 | 
				
			||||||
			err = -EFAULT;
 | 
								err = -EFAULT;
 | 
				
			||||||
		return err;
 | 
						} else {
 | 
				
			||||||
 | 
							struct ifreq ifr;
 | 
				
			||||||
 | 
							bool need_copyout;
 | 
				
			||||||
 | 
							if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
 | 
				
			||||||
 | 
								return -EFAULT;
 | 
				
			||||||
 | 
							err = dev_ioctl(net, cmd, &ifr, &need_copyout);
 | 
				
			||||||
 | 
							if (!err && need_copyout)
 | 
				
			||||||
 | 
								if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
 | 
				
			||||||
 | 
									return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
	return dev_ioctl(net, cmd, argp);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1000,8 +1007,15 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 | 
				
			||||||
	sock = file->private_data;
 | 
						sock = file->private_data;
 | 
				
			||||||
	sk = sock->sk;
 | 
						sk = sock->sk;
 | 
				
			||||||
	net = sock_net(sk);
 | 
						net = sock_net(sk);
 | 
				
			||||||
	if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
 | 
						if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
 | 
				
			||||||
		err = dev_ioctl(net, cmd, argp);
 | 
							struct ifreq ifr;
 | 
				
			||||||
 | 
							bool need_copyout;
 | 
				
			||||||
 | 
							if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
 | 
				
			||||||
 | 
								return -EFAULT;
 | 
				
			||||||
 | 
							err = dev_ioctl(net, cmd, &ifr, &need_copyout);
 | 
				
			||||||
 | 
							if (!err && need_copyout)
 | 
				
			||||||
 | 
								if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
 | 
				
			||||||
 | 
									return -EFAULT;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
#ifdef CONFIG_WEXT_CORE
 | 
					#ifdef CONFIG_WEXT_CORE
 | 
				
			||||||
	if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
 | 
						if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
 | 
				
			||||||
| 
						 | 
					@ -2695,9 +2709,9 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct compat_ethtool_rxnfc __user *compat_rxnfc;
 | 
						struct compat_ethtool_rxnfc __user *compat_rxnfc;
 | 
				
			||||||
	bool convert_in = false, convert_out = false;
 | 
						bool convert_in = false, convert_out = false;
 | 
				
			||||||
	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
 | 
						size_t buf_size = 0;
 | 
				
			||||||
	struct ethtool_rxnfc __user *rxnfc;
 | 
						struct ethtool_rxnfc __user *rxnfc = NULL;
 | 
				
			||||||
	struct ifreq __user *ifr;
 | 
						struct ifreq ifr;
 | 
				
			||||||
	u32 rule_cnt = 0, actual_rule_cnt;
 | 
						u32 rule_cnt = 0, actual_rule_cnt;
 | 
				
			||||||
	u32 ethcmd;
 | 
						u32 ethcmd;
 | 
				
			||||||
	u32 data;
 | 
						u32 data;
 | 
				
			||||||
| 
						 | 
					@ -2734,18 +2748,14 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 | 
				
			||||||
	case ETHTOOL_SRXCLSRLDEL:
 | 
						case ETHTOOL_SRXCLSRLDEL:
 | 
				
			||||||
		buf_size += sizeof(struct ethtool_rxnfc);
 | 
							buf_size += sizeof(struct ethtool_rxnfc);
 | 
				
			||||||
		convert_in = true;
 | 
							convert_in = true;
 | 
				
			||||||
 | 
							rxnfc = compat_alloc_user_space(buf_size);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ifr = compat_alloc_user_space(buf_size);
 | 
						if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 | 
				
			||||||
	rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (put_user(convert_in ? rxnfc : compat_ptr(data),
 | 
						ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
 | 
				
			||||||
		     &ifr->ifr_ifru.ifru_data))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (convert_in) {
 | 
						if (convert_in) {
 | 
				
			||||||
		/* We expect there to be holes between fs.m_ext and
 | 
							/* We expect there to be holes between fs.m_ext and
 | 
				
			||||||
| 
						 | 
					@ -2773,7 +2783,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 | 
				
			||||||
			return -EFAULT;
 | 
								return -EFAULT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
 | 
						ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2814,50 +2824,43 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
 | 
					static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void __user *uptr;
 | 
					 | 
				
			||||||
	compat_uptr_t uptr32;
 | 
						compat_uptr_t uptr32;
 | 
				
			||||||
	struct ifreq __user *uifr;
 | 
						struct ifreq ifr;
 | 
				
			||||||
 | 
						void __user *saved;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uifr = compat_alloc_user_space(sizeof(*uifr));
 | 
						if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
 | 
				
			||||||
	if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
 | 
						if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uptr = compat_ptr(uptr32);
 | 
						saved = ifr.ifr_settings.ifs_ifsu.raw_hdlc;
 | 
				
			||||||
 | 
						ifr.ifr_settings.ifs_ifsu.raw_hdlc = compat_ptr(uptr32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc))
 | 
						err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
 | 
				
			||||||
		return -EFAULT;
 | 
						if (!err) {
 | 
				
			||||||
 | 
							ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
 | 
				
			||||||
	return dev_ioctl(net, SIOCWANDEV, uifr);
 | 
							if (copy_to_user(uifr32, &ifr, sizeof(struct compat_ifreq)))
 | 
				
			||||||
 | 
								err = -EFAULT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
 | 
					/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
 | 
				
			||||||
static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
 | 
					static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
 | 
				
			||||||
				 struct compat_ifreq __user *u_ifreq32)
 | 
									 struct compat_ifreq __user *u_ifreq32)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ifreq __user *u_ifreq64;
 | 
						struct ifreq ifreq;
 | 
				
			||||||
	char tmp_buf[IFNAMSIZ];
 | 
					 | 
				
			||||||
	void __user *data64;
 | 
					 | 
				
			||||||
	u32 data32;
 | 
						u32 data32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
 | 
						if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
 | 
				
			||||||
			   IFNAMSIZ))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
 | 
						if (get_user(data32, &u_ifreq32->ifr_data))
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
	data64 = compat_ptr(data32);
 | 
						ifreq.ifr_data = compat_ptr(data32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
 | 
						return dev_ioctl(net, cmd, &ifreq, NULL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
 | 
					 | 
				
			||||||
			 IFNAMSIZ))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
	if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
 | 
					 | 
				
			||||||
		return -EFAULT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return dev_ioctl(net, cmd, u_ifreq64);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 | 
					static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 | 
				
			||||||
| 
						 | 
					@ -2865,7 +2868,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ifreq ifr;
 | 
						struct ifreq ifr;
 | 
				
			||||||
	struct compat_ifmap __user *uifmap32;
 | 
						struct compat_ifmap __user *uifmap32;
 | 
				
			||||||
	mm_segment_t old_fs;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uifmap32 = &uifr32->ifr_ifru.ifru_map;
 | 
						uifmap32 = &uifr32->ifr_ifru.ifru_map;
 | 
				
			||||||
| 
						 | 
					@ -2879,10 +2881,7 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return -EFAULT;
 | 
							return -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	old_fs = get_fs();
 | 
						err = dev_ioctl(net, cmd, &ifr, NULL);
 | 
				
			||||||
	set_fs(KERNEL_DS);
 | 
					 | 
				
			||||||
	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
 | 
					 | 
				
			||||||
	set_fs(old_fs);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cmd == SIOCGIFMAP && !err) {
 | 
						if (cmd == SIOCGIFMAP && !err) {
 | 
				
			||||||
		err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
 | 
							err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue