Merge branch 'rebased-net-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
8ec59b44a0
|
@ -173,7 +173,7 @@ static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
|
|||
}
|
||||
|
||||
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *);
|
||||
void devinet_init(void);
|
||||
struct in_device *inetdev_by_index(struct net *, int);
|
||||
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
|
||||
|
|
|
@ -306,7 +306,6 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset,
|
|||
size_t size, int flags);
|
||||
int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
|
||||
size_t size, int flags);
|
||||
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
|
||||
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
|
||||
|
||||
/* Routine returns the IP overhead imposed by a (caller-protected) socket. */
|
||||
|
|
|
@ -2761,7 +2761,8 @@ static inline bool dev_validate_header(const struct net_device *dev,
|
|||
return false;
|
||||
}
|
||||
|
||||
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
|
||||
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr,
|
||||
int len, int size);
|
||||
int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
|
||||
static inline int unregister_gifconf(unsigned int family)
|
||||
{
|
||||
|
@ -3314,7 +3315,9 @@ int netdev_rx_handler_register(struct net_device *dev,
|
|||
void netdev_rx_handler_unregister(struct net_device *dev);
|
||||
|
||||
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_ethtool(struct net *net, struct ifreq *);
|
||||
unsigned int dev_get_flags(const struct net_device *);
|
||||
int __dev_change_flags(struct net_device *, unsigned int flags);
|
||||
|
|
|
@ -217,7 +217,7 @@ unsigned int inet_addr_type_dev_table(struct net *net,
|
|||
const struct net_device *dev,
|
||||
__be32 addr);
|
||||
void ip_rt_multicast_event(struct in_device *);
|
||||
int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
|
||||
int ip_rt_ioctl(struct net *, unsigned int cmd, struct rtentry *rt);
|
||||
void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
|
||||
struct rtable *rt_dst_alloc(struct net_device *dev,
|
||||
unsigned int flags, u16 type,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
struct net;
|
||||
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
|
||||
int wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||
void __user *arg);
|
||||
int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
@ -15,7 +15,7 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
|
|||
struct iw_statistics *get_wireless_stats(struct net_device *dev);
|
||||
int call_commit_handler(struct net_device *dev);
|
||||
#else
|
||||
static inline int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
|
||||
static inline int wext_handle_ioctl(struct net *net, unsigned int cmd,
|
||||
void __user *arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
|
|
|
@ -18,26 +18,10 @@
|
|||
* 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;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
ifr->ifr_name[IFNAMSIZ-1] = 0;
|
||||
return netdev_get_name(net, ifr->ifr_name, ifr->ifr_ifindex);
|
||||
}
|
||||
|
||||
static gifconf_func_t *gifconf_list[NPROTO];
|
||||
|
@ -66,9 +50,8 @@ EXPORT_SYMBOL(register_gifconf);
|
|||
* Thus we will need a 'compatibility mode'.
|
||||
*/
|
||||
|
||||
static int dev_ifconf(struct net *net, char __user *arg)
|
||||
int dev_ifconf(struct net *net, struct ifconf *ifc, int size)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
struct net_device *dev;
|
||||
char __user *pos;
|
||||
int len;
|
||||
|
@ -79,11 +62,8 @@ static int dev_ifconf(struct net *net, char __user *arg)
|
|||
* Fetch the caller's info block.
|
||||
*/
|
||||
|
||||
if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
|
||||
return -EFAULT;
|
||||
|
||||
pos = ifc.ifc_buf;
|
||||
len = ifc.ifc_len;
|
||||
pos = ifc->ifc_buf;
|
||||
len = ifc->ifc_len;
|
||||
|
||||
/*
|
||||
* Loop over the interfaces, and write an info block for each.
|
||||
|
@ -95,10 +75,10 @@ static int dev_ifconf(struct net *net, char __user *arg)
|
|||
if (gifconf_list[i]) {
|
||||
int done;
|
||||
if (!pos)
|
||||
done = gifconf_list[i](dev, NULL, 0);
|
||||
done = gifconf_list[i](dev, NULL, 0, size);
|
||||
else
|
||||
done = gifconf_list[i](dev, pos + total,
|
||||
len - total);
|
||||
len - total, size);
|
||||
if (done < 0)
|
||||
return -EFAULT;
|
||||
total += done;
|
||||
|
@ -109,12 +89,12 @@ static int dev_ifconf(struct net *net, char __user *arg)
|
|||
/*
|
||||
* All done. Write the updated control block back to the caller.
|
||||
*/
|
||||
ifc.ifc_len = total;
|
||||
ifc->ifc_len = total;
|
||||
|
||||
/*
|
||||
* Both BSD and Solaris return 0 here, so we do too.
|
||||
*/
|
||||
return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -406,53 +386,24 @@ EXPORT_SYMBOL(dev_load);
|
|||
* 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;
|
||||
char *colon;
|
||||
|
||||
/* One special case: SIOCGIFCONF takes ifconf argument
|
||||
and requires shared lock, because it sleeps writing
|
||||
to user space.
|
||||
*/
|
||||
|
||||
if (cmd == SIOCGIFCONF) {
|
||||
rtnl_lock();
|
||||
ret = dev_ifconf(net, (char __user *) arg);
|
||||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
if (need_copyout)
|
||||
*need_copyout = true;
|
||||
if (cmd == SIOCGIFNAME)
|
||||
return dev_ifname(net, (struct ifreq __user *)arg);
|
||||
return dev_ifname(net, ifr);
|
||||
|
||||
/*
|
||||
* Take care of Wireless Extensions. Unfortunately struct iwreq
|
||||
* isn't a proper subset of struct ifreq (it's 8 byte shorter)
|
||||
* so we need to treat it specially, otherwise applications may
|
||||
* fault if the struct they're passing happens to land at the
|
||||
* end of a mapped page.
|
||||
*/
|
||||
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
|
||||
struct iwreq iwr;
|
||||
ifr->ifr_name[IFNAMSIZ-1] = 0;
|
||||
|
||||
if (copy_from_user(&iwr, arg, sizeof(iwr)))
|
||||
return -EFAULT;
|
||||
|
||||
iwr.ifr_name[sizeof(iwr.ifr_name) - 1] = 0;
|
||||
|
||||
return wext_handle_ioctl(net, &iwr, cmd, arg);
|
||||
}
|
||||
|
||||
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
|
||||
return -EFAULT;
|
||||
|
||||
ifr.ifr_name[IFNAMSIZ-1] = 0;
|
||||
|
||||
colon = strchr(ifr.ifr_name, ':');
|
||||
colon = strchr(ifr->ifr_name, ':');
|
||||
if (colon)
|
||||
*colon = 0;
|
||||
|
||||
dev_load(net, ifr->ifr_name);
|
||||
|
||||
/*
|
||||
* See which interface the caller is talking about.
|
||||
*/
|
||||
|
@ -472,31 +423,19 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
case SIOCGIFMAP:
|
||||
case SIOCGIFINDEX:
|
||||
case SIOCGIFTXQLEN:
|
||||
dev_load(net, ifr.ifr_name);
|
||||
rcu_read_lock();
|
||||
ret = dev_ifsioc_locked(net, &ifr, cmd);
|
||||
ret = dev_ifsioc_locked(net, ifr, cmd);
|
||||
rcu_read_unlock();
|
||||
if (!ret) {
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
if (copy_to_user(arg, &ifr,
|
||||
sizeof(struct ifreq)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
return ret;
|
||||
|
||||
case SIOCETHTOOL:
|
||||
dev_load(net, ifr.ifr_name);
|
||||
rtnl_lock();
|
||||
ret = dev_ethtool(net, &ifr);
|
||||
ret = dev_ethtool(net, ifr);
|
||||
rtnl_unlock();
|
||||
if (!ret) {
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
if (copy_to_user(arg, &ifr,
|
||||
sizeof(struct ifreq)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
return ret;
|
||||
|
||||
/*
|
||||
|
@ -510,17 +449,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
case SIOCSIFNAME:
|
||||
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
dev_load(net, ifr.ifr_name);
|
||||
rtnl_lock();
|
||||
ret = dev_ifsioc(net, &ifr, cmd);
|
||||
ret = dev_ifsioc(net, ifr, cmd);
|
||||
rtnl_unlock();
|
||||
if (!ret) {
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
if (copy_to_user(arg, &ifr,
|
||||
sizeof(struct ifreq)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
return ret;
|
||||
|
||||
/*
|
||||
|
@ -561,10 +494,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
/* fall through */
|
||||
case SIOCBONDSLAVEINFOQUERY:
|
||||
case SIOCBONDINFOQUERY:
|
||||
dev_load(net, ifr.ifr_name);
|
||||
rtnl_lock();
|
||||
ret = dev_ifsioc(net, &ifr, cmd);
|
||||
ret = dev_ifsioc(net, ifr, cmd);
|
||||
rtnl_unlock();
|
||||
if (need_copyout)
|
||||
*need_copyout = false;
|
||||
return ret;
|
||||
|
||||
case SIOCGIFMEM:
|
||||
|
@ -584,13 +518,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
cmd == SIOCGHWTSTAMP ||
|
||||
(cmd >= SIOCDEVPRIVATE &&
|
||||
cmd <= SIOCDEVPRIVATE + 15)) {
|
||||
dev_load(net, ifr.ifr_name);
|
||||
rtnl_lock();
|
||||
ret = dev_ifsioc(net, &ifr, cmd);
|
||||
ret = dev_ifsioc(net, ifr, cmd);
|
||||
rtnl_unlock();
|
||||
if (!ret && copy_to_user(arg, &ifr,
|
||||
sizeof(struct ifreq)))
|
||||
ret = -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
return -ENOTTY;
|
||||
|
|
|
@ -872,6 +872,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
struct sock *sk = sock->sk;
|
||||
int err = 0;
|
||||
struct net *net = sock_net(sk);
|
||||
void __user *p = (void __user *)arg;
|
||||
struct ifreq ifr;
|
||||
struct rtentry rt;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGSTAMP:
|
||||
|
@ -882,8 +885,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
|
||||
return -EFAULT;
|
||||
err = ip_rt_ioctl(net, cmd, &rt);
|
||||
break;
|
||||
case SIOCRTMSG:
|
||||
err = ip_rt_ioctl(net, cmd, (void __user *)arg);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case SIOCDARP:
|
||||
case SIOCGARP:
|
||||
|
@ -891,17 +898,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
err = arp_ioctl(net, cmd, (void __user *)arg);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
case SIOCSIFADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCGIFPFLAGS:
|
||||
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
|
||||
return -EFAULT;
|
||||
err = devinet_ioctl(net, cmd, &ifr);
|
||||
if (!err && copy_to_user(p, &ifr, sizeof(struct ifreq)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR:
|
||||
case SIOCSIFBRDADDR:
|
||||
case SIOCSIFNETMASK:
|
||||
case SIOCSIFDSTADDR:
|
||||
case SIOCSIFPFLAGS:
|
||||
case SIOCGIFPFLAGS:
|
||||
case SIOCSIFFLAGS:
|
||||
err = devinet_ioctl(net, cmd, (void __user *)arg);
|
||||
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
|
||||
return -EFAULT;
|
||||
err = devinet_ioctl(net, cmd, &ifr);
|
||||
break;
|
||||
default:
|
||||
if (sk->sk_prot->ioctl)
|
||||
|
|
|
@ -946,11 +946,10 @@ static int inet_abc_len(__be32 addr)
|
|||
}
|
||||
|
||||
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_in sin_orig;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
|
||||
struct in_device *in_dev;
|
||||
struct in_ifaddr **ifap = NULL;
|
||||
struct in_ifaddr *ifa = NULL;
|
||||
|
@ -959,22 +958,16 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
int ret = -EFAULT;
|
||||
int tryaddrmatch = 0;
|
||||
|
||||
/*
|
||||
* Fetch the caller's info block into kernel space
|
||||
*/
|
||||
|
||||
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
|
||||
goto out;
|
||||
ifr.ifr_name[IFNAMSIZ - 1] = 0;
|
||||
ifr->ifr_name[IFNAMSIZ - 1] = 0;
|
||||
|
||||
/* save original address for comparison */
|
||||
memcpy(&sin_orig, sin, sizeof(*sin));
|
||||
|
||||
colon = strchr(ifr.ifr_name, ':');
|
||||
colon = strchr(ifr->ifr_name, ':');
|
||||
if (colon)
|
||||
*colon = 0;
|
||||
|
||||
dev_load(net, ifr.ifr_name);
|
||||
dev_load(net, ifr->ifr_name);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGIFADDR: /* Get interface address */
|
||||
|
@ -1014,7 +1007,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
rtnl_lock();
|
||||
|
||||
ret = -ENODEV;
|
||||
dev = __dev_get_by_name(net, ifr.ifr_name);
|
||||
dev = __dev_get_by_name(net, ifr->ifr_name);
|
||||
if (!dev)
|
||||
goto done;
|
||||
|
||||
|
@ -1031,7 +1024,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
This is checked above. */
|
||||
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
|
||||
ifap = &ifa->ifa_next) {
|
||||
if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
|
||||
if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
|
||||
sin_orig.sin_addr.s_addr ==
|
||||
ifa->ifa_local) {
|
||||
break; /* found */
|
||||
|
@ -1044,7 +1037,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ifa) {
|
||||
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
|
||||
ifap = &ifa->ifa_next)
|
||||
if (!strcmp(ifr.ifr_name, ifa->ifa_label))
|
||||
if (!strcmp(ifr->ifr_name, ifa->ifa_label))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1056,19 +1049,19 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
switch (cmd) {
|
||||
case SIOCGIFADDR: /* Get interface address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_local;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFBRDADDR: /* Get the broadcast address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_broadcast;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFDSTADDR: /* Get the destination address */
|
||||
sin->sin_addr.s_addr = ifa->ifa_address;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCGIFNETMASK: /* Get the netmask for the interface */
|
||||
sin->sin_addr.s_addr = ifa->ifa_mask;
|
||||
goto rarok;
|
||||
break;
|
||||
|
||||
case SIOCSIFFLAGS:
|
||||
if (colon) {
|
||||
|
@ -1076,11 +1069,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ifa)
|
||||
break;
|
||||
ret = 0;
|
||||
if (!(ifr.ifr_flags & IFF_UP))
|
||||
if (!(ifr->ifr_flags & IFF_UP))
|
||||
inet_del_ifa(in_dev, ifap, 1);
|
||||
break;
|
||||
}
|
||||
ret = dev_change_flags(dev, ifr.ifr_flags);
|
||||
ret = dev_change_flags(dev, ifr->ifr_flags);
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR: /* Set interface address (and family) */
|
||||
|
@ -1095,7 +1088,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
break;
|
||||
INIT_HLIST_NODE(&ifa->hash);
|
||||
if (colon)
|
||||
memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
|
||||
memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ);
|
||||
else
|
||||
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
|
||||
} else {
|
||||
|
@ -1182,28 +1175,27 @@ done:
|
|||
rtnl_unlock();
|
||||
out:
|
||||
return ret;
|
||||
rarok:
|
||||
rtnl_unlock();
|
||||
ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
|
||||
static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size)
|
||||
{
|
||||
struct in_device *in_dev = __in_dev_get_rtnl(dev);
|
||||
struct in_ifaddr *ifa;
|
||||
struct ifreq ifr;
|
||||
int done = 0;
|
||||
|
||||
if (WARN_ON(size > sizeof(struct ifreq)))
|
||||
goto out;
|
||||
|
||||
if (!in_dev)
|
||||
goto out;
|
||||
|
||||
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
|
||||
if (!buf) {
|
||||
done += sizeof(ifr);
|
||||
done += size;
|
||||
continue;
|
||||
}
|
||||
if (len < (int) sizeof(ifr))
|
||||
if (len < size)
|
||||
break;
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
strcpy(ifr.ifr_name, ifa->ifa_label);
|
||||
|
@ -1212,13 +1204,12 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
|
|||
(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
|
||||
ifa->ifa_local;
|
||||
|
||||
if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) {
|
||||
if (copy_to_user(buf + done, &ifr, size)) {
|
||||
done = -EFAULT;
|
||||
break;
|
||||
}
|
||||
buf += sizeof(struct ifreq);
|
||||
len -= sizeof(struct ifreq);
|
||||
done += sizeof(struct ifreq);
|
||||
len -= size;
|
||||
done += size;
|
||||
}
|
||||
out:
|
||||
return done;
|
||||
|
|
|
@ -587,10 +587,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
|
|||
* Handle IP routing ioctl calls.
|
||||
* These are used to manipulate the routing tables
|
||||
*/
|
||||
int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
|
||||
{
|
||||
struct fib_config cfg;
|
||||
struct rtentry rt;
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -599,11 +598,8 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
|||
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (copy_from_user(&rt, arg, sizeof(rt)))
|
||||
return -EFAULT;
|
||||
|
||||
rtnl_lock();
|
||||
err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
|
||||
err = rtentry_to_fib_config(net, cmd, rt, &cfg);
|
||||
if (err == 0) {
|
||||
struct fib_table *tb;
|
||||
|
||||
|
|
|
@ -329,39 +329,6 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
|
|||
sin->sin_port = port;
|
||||
}
|
||||
|
||||
static int __init ic_devinet_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = devinet_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init ic_dev_ioctl(unsigned int cmd, struct ifreq *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = dev_ioctl(&init_net, cmd, (struct ifreq __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __init ic_route_ioctl(unsigned int cmd, struct rtentry *arg)
|
||||
{
|
||||
int res;
|
||||
|
||||
mm_segment_t oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
res = ip_rt_ioctl(&init_net, cmd, (void __user *) arg);
|
||||
set_fs(oldfs);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up interface addresses and routes.
|
||||
*/
|
||||
|
@ -375,19 +342,19 @@ static int __init ic_setup_if(void)
|
|||
memset(&ir, 0, sizeof(ir));
|
||||
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name);
|
||||
set_sockaddr(sin, ic_myaddr, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFADDR, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFADDR, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface address (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
set_sockaddr(sin, ic_netmask, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFNETMASK, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface netmask (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
}
|
||||
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
|
||||
if ((err = ic_devinet_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
|
||||
if ((err = devinet_ioctl(&init_net, SIOCSIFBRDADDR, &ir)) < 0) {
|
||||
pr_err("IP-Config: Unable to set interface broadcast address (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
|
@ -397,11 +364,11 @@ static int __init ic_setup_if(void)
|
|||
* out, we'll try to muddle along.
|
||||
*/
|
||||
if (ic_dev_mtu != 0) {
|
||||
strcpy(ir.ifr_name, ic_dev->dev->name);
|
||||
ir.ifr_mtu = ic_dev_mtu;
|
||||
if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
|
||||
rtnl_lock();
|
||||
if ((err = dev_set_mtu(ic_dev->dev, ic_dev_mtu)) < 0)
|
||||
pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n",
|
||||
ic_dev_mtu, err);
|
||||
rtnl_unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -423,7 +390,7 @@ static int __init ic_setup_routes(void)
|
|||
set_sockaddr((struct sockaddr_in *) &rm.rt_genmask, 0, 0);
|
||||
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
|
||||
rm.rt_flags = RTF_UP | RTF_GATEWAY;
|
||||
if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
|
||||
if ((err = ip_rt_ioctl(&init_net, SIOCADDRT, &rm)) < 0) {
|
||||
pr_err("IP-Config: Cannot add default route (%d)\n",
|
||||
err);
|
||||
return -1;
|
||||
|
|
271
net/socket.c
271
net/socket.c
|
@ -961,9 +961,28 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
|
|||
* If this ioctl is unknown try to hand it down
|
||||
* to the NIC driver.
|
||||
*/
|
||||
if (err == -ENOIOCTLCMD)
|
||||
err = dev_ioctl(net, cmd, argp);
|
||||
if (err != -ENOIOCTLCMD)
|
||||
return err;
|
||||
|
||||
if (cmd == SIOCGIFCONF) {
|
||||
struct ifconf ifc;
|
||||
if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
|
||||
return -EFAULT;
|
||||
rtnl_lock();
|
||||
err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
|
||||
rtnl_unlock();
|
||||
if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
|
||||
err = -EFAULT;
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -988,12 +1007,19 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
|||
sock = file->private_data;
|
||||
sk = sock->sk;
|
||||
net = sock_net(sk);
|
||||
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
|
||||
err = dev_ioctl(net, cmd, argp);
|
||||
if (unlikely(cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))) {
|
||||
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
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
|
||||
err = dev_ioctl(net, cmd, argp);
|
||||
err = wext_handle_ioctl(net, cmd, argp);
|
||||
} else
|
||||
#endif
|
||||
switch (cmd) {
|
||||
|
@ -2654,89 +2680,25 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32)
|
||||
{
|
||||
struct ifreq __user *uifr;
|
||||
int err;
|
||||
|
||||
uifr = compat_alloc_user_space(sizeof(struct ifreq));
|
||||
if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
|
||||
err = dev_ioctl(net, SIOCGIFNAME, uifr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
|
||||
static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
|
||||
{
|
||||
struct compat_ifconf ifc32;
|
||||
struct ifconf ifc;
|
||||
struct ifconf __user *uifc;
|
||||
struct compat_ifreq __user *ifr32;
|
||||
struct ifreq __user *ifr;
|
||||
unsigned int i, j;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))
|
||||
return -EFAULT;
|
||||
|
||||
memset(&ifc, 0, sizeof(ifc));
|
||||
if (ifc32.ifcbuf == 0) {
|
||||
ifc32.ifc_len = 0;
|
||||
ifc.ifc_len = 0;
|
||||
ifc.ifc_req = NULL;
|
||||
uifc = compat_alloc_user_space(sizeof(struct ifconf));
|
||||
} else {
|
||||
size_t len = ((ifc32.ifc_len / sizeof(struct compat_ifreq)) + 1) *
|
||||
sizeof(struct ifreq);
|
||||
uifc = compat_alloc_user_space(sizeof(struct ifconf) + len);
|
||||
ifc.ifc_len = len;
|
||||
ifr = ifc.ifc_req = (void __user *)(uifc + 1);
|
||||
ifr32 = compat_ptr(ifc32.ifcbuf);
|
||||
for (i = 0; i < ifc32.ifc_len; i += sizeof(struct compat_ifreq)) {
|
||||
if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
ifr++;
|
||||
ifr32++;
|
||||
}
|
||||
}
|
||||
if (copy_to_user(uifc, &ifc, sizeof(struct ifconf)))
|
||||
return -EFAULT;
|
||||
ifc.ifc_len = ifc32.ifc_len;
|
||||
ifc.ifc_req = compat_ptr(ifc32.ifcbuf);
|
||||
|
||||
err = dev_ioctl(net, SIOCGIFCONF, uifc);
|
||||
rtnl_lock();
|
||||
err = dev_ifconf(net, &ifc, sizeof(struct compat_ifreq));
|
||||
rtnl_unlock();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
|
||||
return -EFAULT;
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
ifr32 = compat_ptr(ifc32.ifcbuf);
|
||||
for (i = 0, j = 0;
|
||||
i + sizeof(struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len;
|
||||
i += sizeof(struct compat_ifreq), j += sizeof(struct ifreq)) {
|
||||
if (copy_in_user(ifr32, ifr, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
ifr32++;
|
||||
ifr++;
|
||||
}
|
||||
|
||||
if (ifc32.ifcbuf == 0) {
|
||||
/* Translate from 64-bit structure multiple to
|
||||
* a 32-bit one.
|
||||
*/
|
||||
i = ifc.ifc_len;
|
||||
i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq));
|
||||
ifc32.ifc_len = i;
|
||||
} else {
|
||||
ifc32.ifc_len = i;
|
||||
}
|
||||
ifc32.ifc_len = ifc.ifc_len;
|
||||
if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -2747,9 +2709,9 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
|
|||
{
|
||||
struct compat_ethtool_rxnfc __user *compat_rxnfc;
|
||||
bool convert_in = false, convert_out = false;
|
||||
size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
|
||||
struct ethtool_rxnfc __user *rxnfc;
|
||||
struct ifreq __user *ifr;
|
||||
size_t buf_size = 0;
|
||||
struct ethtool_rxnfc __user *rxnfc = NULL;
|
||||
struct ifreq ifr;
|
||||
u32 rule_cnt = 0, actual_rule_cnt;
|
||||
u32 ethcmd;
|
||||
u32 data;
|
||||
|
@ -2786,18 +2748,14 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
|
|||
case ETHTOOL_SRXCLSRLDEL:
|
||||
buf_size += sizeof(struct ethtool_rxnfc);
|
||||
convert_in = true;
|
||||
rxnfc = compat_alloc_user_space(buf_size);
|
||||
break;
|
||||
}
|
||||
|
||||
ifr = compat_alloc_user_space(buf_size);
|
||||
rxnfc = (void __user *)ifr + ALIGN(sizeof(struct ifreq), 8);
|
||||
|
||||
if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
|
||||
if (copy_from_user(&ifr.ifr_name, &ifr32->ifr_name, IFNAMSIZ))
|
||||
return -EFAULT;
|
||||
|
||||
if (put_user(convert_in ? rxnfc : compat_ptr(data),
|
||||
&ifr->ifr_ifru.ifru_data))
|
||||
return -EFAULT;
|
||||
ifr.ifr_data = convert_in ? rxnfc : (void __user *)compat_rxnfc;
|
||||
|
||||
if (convert_in) {
|
||||
/* We expect there to be holes between fs.m_ext and
|
||||
|
@ -2825,7 +2783,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = dev_ioctl(net, SIOCETHTOOL, ifr);
|
||||
ret = dev_ioctl(net, SIOCETHTOOL, &ifr, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -2866,113 +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)
|
||||
{
|
||||
void __user *uptr;
|
||||
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_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
|
||||
if (copy_from_user(&ifr, uifr32, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu))
|
||||
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))
|
||||
return -EFAULT;
|
||||
|
||||
return dev_ioctl(net, SIOCWANDEV, uifr);
|
||||
}
|
||||
|
||||
static int bond_ioctl(struct net *net, unsigned int cmd,
|
||||
struct compat_ifreq __user *ifr32)
|
||||
{
|
||||
struct ifreq kifr;
|
||||
mm_segment_t old_fs;
|
||||
int err;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCBONDENSLAVE:
|
||||
case SIOCBONDRELEASE:
|
||||
case SIOCBONDSETHWADDR:
|
||||
case SIOCBONDCHANGEACTIVE:
|
||||
if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
|
||||
return -EFAULT;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
err = dev_ioctl(net, cmd,
|
||||
(struct ifreq __user __force *) &kifr);
|
||||
set_fs(old_fs);
|
||||
|
||||
return err;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
err = dev_ioctl(net, SIOCWANDEV, &ifr, NULL);
|
||||
if (!err) {
|
||||
ifr.ifr_settings.ifs_ifsu.raw_hdlc = saved;
|
||||
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 */
|
||||
static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
|
||||
struct compat_ifreq __user *u_ifreq32)
|
||||
{
|
||||
struct ifreq __user *u_ifreq64;
|
||||
char tmp_buf[IFNAMSIZ];
|
||||
void __user *data64;
|
||||
struct ifreq ifreq;
|
||||
u32 data32;
|
||||
|
||||
if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
|
||||
IFNAMSIZ))
|
||||
if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
|
||||
return -EFAULT;
|
||||
if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
|
||||
if (get_user(data32, &u_ifreq32->ifr_data))
|
||||
return -EFAULT;
|
||||
data64 = compat_ptr(data32);
|
||||
ifreq.ifr_data = compat_ptr(data32);
|
||||
|
||||
u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
|
||||
|
||||
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 dev_ifsioc(struct net *net, struct socket *sock,
|
||||
unsigned int cmd, struct compat_ifreq __user *uifr32)
|
||||
{
|
||||
struct ifreq __user *uifr;
|
||||
int err;
|
||||
|
||||
uifr = compat_alloc_user_space(sizeof(*uifr));
|
||||
if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
|
||||
return -EFAULT;
|
||||
|
||||
err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
|
||||
|
||||
if (!err) {
|
||||
switch (cmd) {
|
||||
case SIOCGIFFLAGS:
|
||||
case SIOCGIFMETRIC:
|
||||
case SIOCGIFMTU:
|
||||
case SIOCGIFMEM:
|
||||
case SIOCGIFHWADDR:
|
||||
case SIOCGIFINDEX:
|
||||
case SIOCGIFADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCGIFPFLAGS:
|
||||
case SIOCGIFTXQLEN:
|
||||
case SIOCGMIIPHY:
|
||||
case SIOCGMIIREG:
|
||||
if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
return dev_ioctl(net, cmd, &ifreq, NULL);
|
||||
}
|
||||
|
||||
static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
|
||||
|
@ -2980,7 +2868,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
|
|||
{
|
||||
struct ifreq ifr;
|
||||
struct compat_ifmap __user *uifmap32;
|
||||
mm_segment_t old_fs;
|
||||
int err;
|
||||
|
||||
uifmap32 = &uifr32->ifr_ifru.ifru_map;
|
||||
|
@ -2994,10 +2881,7 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
|
|||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
err = dev_ioctl(net, cmd, (void __user __force *)&ifr);
|
||||
set_fs(old_fs);
|
||||
err = dev_ioctl(net, cmd, &ifr, NULL);
|
||||
|
||||
if (cmd == SIOCGIFMAP && !err) {
|
||||
err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
|
||||
|
@ -3130,10 +3014,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
|
|||
case SIOCSIFBR:
|
||||
case SIOCGIFBR:
|
||||
return old_bridge_ioctl(argp);
|
||||
case SIOCGIFNAME:
|
||||
return dev_ifname32(net, argp);
|
||||
case SIOCGIFCONF:
|
||||
return dev_ifconf(net, argp);
|
||||
return compat_dev_ifconf(net, argp);
|
||||
case SIOCETHTOOL:
|
||||
return ethtool_ioctl(net, argp);
|
||||
case SIOCWANDEV:
|
||||
|
@ -3141,11 +3023,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
|
|||
case SIOCGIFMAP:
|
||||
case SIOCSIFMAP:
|
||||
return compat_sioc_ifmap(net, cmd, argp);
|
||||
case SIOCBONDENSLAVE:
|
||||
case SIOCBONDRELEASE:
|
||||
case SIOCBONDSETHWADDR:
|
||||
case SIOCBONDCHANGEACTIVE:
|
||||
return bond_ioctl(net, cmd, argp);
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
return routing_ioctl(net, sock, cmd, argp);
|
||||
|
@ -3205,12 +3082,15 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
|
|||
case SIOCGMIIPHY:
|
||||
case SIOCGMIIREG:
|
||||
case SIOCSMIIREG:
|
||||
return dev_ifsioc(net, sock, cmd, argp);
|
||||
|
||||
case SIOCSARP:
|
||||
case SIOCGARP:
|
||||
case SIOCDARP:
|
||||
case SIOCATMARK:
|
||||
case SIOCBONDENSLAVE:
|
||||
case SIOCBONDRELEASE:
|
||||
case SIOCBONDSETHWADDR:
|
||||
case SIOCBONDCHANGEACTIVE:
|
||||
case SIOCGIFNAME:
|
||||
return sock_do_ioctl(net, sock, cmd, arg);
|
||||
}
|
||||
|
||||
|
@ -3365,19 +3245,6 @@ int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
|
|||
}
|
||||
EXPORT_SYMBOL(kernel_sendpage_locked);
|
||||
|
||||
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
|
||||
{
|
||||
mm_segment_t oldfs = get_fs();
|
||||
int err;
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
err = sock->ops->ioctl(sock, cmd, arg);
|
||||
set_fs(oldfs);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_sock_ioctl);
|
||||
|
||||
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
|
||||
{
|
||||
return sock->ops->shutdown(sock, how);
|
||||
|
|
|
@ -1035,18 +1035,23 @@ static int ioctl_standard_call(struct net_device * dev,
|
|||
}
|
||||
|
||||
|
||||
int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
|
||||
void __user *arg)
|
||||
int wext_handle_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
{
|
||||
struct iw_request_info info = { .cmd = cmd, .flags = 0 };
|
||||
struct iwreq iwr;
|
||||
int ret;
|
||||
|
||||
ret = wext_ioctl_dispatch(net, iwr, cmd, &info,
|
||||
if (copy_from_user(&iwr, arg, sizeof(iwr)))
|
||||
return -EFAULT;
|
||||
|
||||
iwr.ifr_name[sizeof(iwr.ifr_name) - 1] = 0;
|
||||
|
||||
ret = wext_ioctl_dispatch(net, &iwr, cmd, &info,
|
||||
ioctl_standard_call,
|
||||
ioctl_private_call);
|
||||
if (ret >= 0 &&
|
||||
IW_IS_GET(cmd) &&
|
||||
copy_to_user(arg, iwr, sizeof(struct iwreq)))
|
||||
copy_to_user(arg, &iwr, sizeof(struct iwreq)))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue