Commit 8ec59b44 authored by David S. Miller's avatar David S. Miller
parents 955bd1d2 5c59e564
...@@ -173,7 +173,7 @@ static inline struct net_device *ip_dev_find(struct net *net, __be32 addr) ...@@ -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 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); void devinet_init(void);
struct in_device *inetdev_by_index(struct net *, int); struct in_device *inetdev_by_index(struct net *, int);
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope); __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, ...@@ -306,7 +306,6 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags); size_t size, int flags);
int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset, int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
size_t size, int flags); 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); int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
/* Routine returns the IP overhead imposed by a (caller-protected) socket. */ /* 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, ...@@ -2761,7 +2761,8 @@ static inline bool dev_validate_header(const struct net_device *dev,
return false; 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); int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
static inline int unregister_gifconf(unsigned int family) static inline int unregister_gifconf(unsigned int family)
{ {
...@@ -3314,7 +3315,9 @@ int netdev_rx_handler_register(struct net_device *dev, ...@@ -3314,7 +3315,9 @@ 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_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 *);
int __dev_change_flags(struct net_device *, unsigned int flags); int __dev_change_flags(struct net_device *, unsigned int flags);
......
...@@ -217,7 +217,7 @@ unsigned int inet_addr_type_dev_table(struct net *net, ...@@ -217,7 +217,7 @@ unsigned int inet_addr_type_dev_table(struct net *net,
const struct net_device *dev, const struct net_device *dev,
__be32 addr); __be32 addr);
void ip_rt_multicast_event(struct in_device *); 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); void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
struct rtable *rt_dst_alloc(struct net_device *dev, struct rtable *rt_dst_alloc(struct net_device *dev,
unsigned int flags, u16 type, unsigned int flags, u16 type,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
struct net; struct net;
#ifdef CONFIG_WEXT_CORE #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); void __user *arg);
int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
unsigned long arg); unsigned long arg);
...@@ -15,7 +15,7 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, ...@@ -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); struct iw_statistics *get_wireless_stats(struct net_device *dev);
int call_commit_handler(struct net_device *dev); int call_commit_handler(struct net_device *dev);
#else #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) void __user *arg)
{ {
return -EINVAL; return -EINVAL;
......
...@@ -18,26 +18,10 @@ ...@@ -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];
...@@ -66,9 +50,8 @@ EXPORT_SYMBOL(register_gifconf); ...@@ -66,9 +50,8 @@ EXPORT_SYMBOL(register_gifconf);
* Thus we will need a 'compatibility mode'. * 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; struct net_device *dev;
char __user *pos; char __user *pos;
int len; int len;
...@@ -79,11 +62,8 @@ static int dev_ifconf(struct net *net, char __user *arg) ...@@ -79,11 +62,8 @@ static int dev_ifconf(struct net *net, char __user *arg)
* Fetch the caller's info block. * Fetch the caller's info block.
*/ */
if (copy_from_user(&ifc, arg, sizeof(struct ifconf))) pos = ifc->ifc_buf;
return -EFAULT; len = ifc->ifc_len;
pos = ifc.ifc_buf;
len = ifc.ifc_len;
/* /*
* Loop over the interfaces, and write an info block for each. * 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) ...@@ -95,10 +75,10 @@ static int dev_ifconf(struct net *net, char __user *arg)
if (gifconf_list[i]) { if (gifconf_list[i]) {
int done; int done;
if (!pos) if (!pos)
done = gifconf_list[i](dev, NULL, 0); done = gifconf_list[i](dev, NULL, 0, size);
else else
done = gifconf_list[i](dev, pos + total, done = gifconf_list[i](dev, pos + total,
len - total); len - total, size);
if (done < 0) if (done < 0)
return -EFAULT; return -EFAULT;
total += done; total += done;
...@@ -109,12 +89,12 @@ static int dev_ifconf(struct net *net, char __user *arg) ...@@ -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. * 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. * 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); ...@@ -406,53 +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;
/* One special case: SIOCGIFCONF takes ifconf argument if (need_copyout)
and requires shared lock, because it sleeps writing *need_copyout = true;
to user space.
*/
if (cmd == SIOCGIFCONF) {
rtnl_lock();
ret = dev_ifconf(net, (char __user *) arg);
rtnl_unlock();
return ret;
}
if (cmd == SIOCGIFNAME) 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;
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); ifr->ifr_name[IFNAMSIZ-1] = 0;
}
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) 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.
*/ */
...@@ -472,31 +423,19 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -472,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;
/* /*
...@@ -510,17 +449,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -510,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;
/* /*
...@@ -561,10 +494,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -561,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:
...@@ -584,13 +518,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -584,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;
......
...@@ -872,6 +872,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -872,6 +872,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int err = 0; int err = 0;
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
void __user *p = (void __user *)arg;
struct ifreq ifr;
struct rtentry rt;
switch (cmd) { switch (cmd) {
case SIOCGSTAMP: case SIOCGSTAMP:
...@@ -882,8 +885,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -882,8 +885,12 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break; break;
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT:
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
return -EFAULT;
err = ip_rt_ioctl(net, cmd, &rt);
break;
case SIOCRTMSG: case SIOCRTMSG:
err = ip_rt_ioctl(net, cmd, (void __user *)arg); err = -EINVAL;
break; break;
case SIOCDARP: case SIOCDARP:
case SIOCGARP: case SIOCGARP:
...@@ -891,17 +898,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -891,17 +898,26 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
err = arp_ioctl(net, cmd, (void __user *)arg); err = arp_ioctl(net, cmd, (void __user *)arg);
break; break;
case SIOCGIFADDR: case SIOCGIFADDR:
case SIOCSIFADDR:
case SIOCGIFBRDADDR: case SIOCGIFBRDADDR:
case SIOCSIFBRDADDR:
case SIOCGIFNETMASK: case SIOCGIFNETMASK:
case SIOCSIFNETMASK:
case SIOCGIFDSTADDR: 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 SIOCSIFDSTADDR:
case SIOCSIFPFLAGS: case SIOCSIFPFLAGS:
case SIOCGIFPFLAGS:
case SIOCSIFFLAGS: 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; break;
default: default:
if (sk->sk_prot->ioctl) if (sk->sk_prot->ioctl)
......
...@@ -946,11 +946,10 @@ static int inet_abc_len(__be32 addr) ...@@ -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_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_device *in_dev;
struct in_ifaddr **ifap = NULL; struct in_ifaddr **ifap = NULL;
struct in_ifaddr *ifa = NULL; struct in_ifaddr *ifa = NULL;
...@@ -959,22 +958,16 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -959,22 +958,16 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
int ret = -EFAULT; int ret = -EFAULT;
int tryaddrmatch = 0; int tryaddrmatch = 0;
/* ifr->ifr_name[IFNAMSIZ - 1] = 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;
/* save original address for comparison */ /* save original address for comparison */
memcpy(&sin_orig, sin, sizeof(*sin)); memcpy(&sin_orig, sin, sizeof(*sin));
colon = strchr(ifr.ifr_name, ':'); colon = strchr(ifr->ifr_name, ':');
if (colon) if (colon)
*colon = 0; *colon = 0;
dev_load(net, ifr.ifr_name); dev_load(net, ifr->ifr_name);
switch (cmd) { switch (cmd) {
case SIOCGIFADDR: /* Get interface address */ case SIOCGIFADDR: /* Get interface address */
...@@ -1014,7 +1007,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1014,7 +1007,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
rtnl_lock(); rtnl_lock();
ret = -ENODEV; ret = -ENODEV;
dev = __dev_get_by_name(net, ifr.ifr_name); dev = __dev_get_by_name(net, ifr->ifr_name);
if (!dev) if (!dev)
goto done; goto done;
...@@ -1031,7 +1024,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1031,7 +1024,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
This is checked above. */ This is checked above. */
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) { 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 == sin_orig.sin_addr.s_addr ==
ifa->ifa_local) { ifa->ifa_local) {
break; /* found */ break; /* found */
...@@ -1044,7 +1037,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1044,7 +1037,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
if (!ifa) { if (!ifa) {
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) ifap = &ifa->ifa_next)
if (!strcmp(ifr.ifr_name, ifa->ifa_label)) if (!strcmp(ifr->ifr_name, ifa->ifa_label))
break; break;
} }
} }
...@@ -1056,19 +1049,19 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1056,19 +1049,19 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
switch (cmd) { switch (cmd) {
case SIOCGIFADDR: /* Get interface address */ case SIOCGIFADDR: /* Get interface address */
sin->sin_addr.s_addr = ifa->ifa_local; sin->sin_addr.s_addr = ifa->ifa_local;
goto rarok; break;
case SIOCGIFBRDADDR: /* Get the broadcast address */ case SIOCGIFBRDADDR: /* Get the broadcast address */
sin->sin_addr.s_addr = ifa->ifa_broadcast; sin->sin_addr.s_addr = ifa->ifa_broadcast;
goto rarok; break;
case SIOCGIFDSTADDR: /* Get the destination address */ case SIOCGIFDSTADDR: /* Get the destination address */
sin->sin_addr.s_addr = ifa->ifa_address; sin->sin_addr.s_addr = ifa->ifa_address;
goto rarok; break;
case SIOCGIFNETMASK: /* Get the netmask for the interface */ case SIOCGIFNETMASK: /* Get the netmask for the interface */
sin->sin_addr.s_addr = ifa->ifa_mask; sin->sin_addr.s_addr = ifa->ifa_mask;
goto rarok; break;
case SIOCSIFFLAGS: case SIOCSIFFLAGS:
if (colon) { if (colon) {
...@@ -1076,11 +1069,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1076,11 +1069,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
if (!ifa) if (!ifa)
break; break;
ret = 0; ret = 0;
if (!(ifr.ifr_flags & IFF_UP)) if (!(ifr->ifr_flags & IFF_UP))
inet_del_ifa(in_dev, ifap, 1); inet_del_ifa(in_dev, ifap, 1);
break; break;
} }
ret = dev_change_flags(dev, ifr.ifr_flags); ret = dev_change_flags(dev, ifr->ifr_flags);
break; break;
case SIOCSIFADDR: /* Set interface address (and family) */ case SIOCSIFADDR: /* Set interface address (and family) */
...@@ -1095,7 +1088,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1095,7 +1088,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
break; break;
INIT_HLIST_NODE(&ifa->hash); INIT_HLIST_NODE(&ifa->hash);
if (colon) if (colon)
memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ);
else else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
} else { } else {
...@@ -1182,28 +1175,27 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -1182,28 +1175,27 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
rtnl_unlock(); rtnl_unlock();
out: out:
return ret; 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_device *in_dev = __in_dev_get_rtnl(dev);
struct in_ifaddr *ifa; struct in_ifaddr *ifa;
struct ifreq ifr; struct ifreq ifr;
int done = 0; int done = 0;
if (WARN_ON(size > sizeof(struct ifreq)))
goto out;
if (!in_dev) if (!in_dev)
goto out; goto out;
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
if (!buf) { if (!buf) {
done += sizeof(ifr); done += size;
continue; continue;
} }
if (len < (int) sizeof(ifr)) if (len < size)
break; break;
memset(&ifr, 0, sizeof(struct ifreq)); memset(&ifr, 0, sizeof(struct ifreq));
strcpy(ifr.ifr_name, ifa->ifa_label); strcpy(ifr.ifr_name, ifa->ifa_label);
...@@ -1212,13 +1204,12 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len) ...@@ -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 = (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
ifa->ifa_local; ifa->ifa_local;
if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) { if (copy_to_user(buf + done, &ifr, size)) {
done = -EFAULT; done = -EFAULT;
break; break;
} }
buf += sizeof(struct ifreq); len -= size;
len -= sizeof(struct ifreq); done += size;
done += sizeof(struct ifreq);
} }
out: out:
return done; return done;
......
...@@ -587,10 +587,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, ...@@ -587,10 +587,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
* Handle IP routing ioctl calls. * Handle IP routing ioctl calls.
* These are used to manipulate the routing tables * 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 fib_config cfg;
struct rtentry rt;
int err; int err;
switch (cmd) { switch (cmd) {
...@@ -599,11 +598,8 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg) ...@@ -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)) if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (copy_from_user(&rt, arg, sizeof(rt)))
return -EFAULT;
rtnl_lock(); rtnl_lock();
err = rtentry_to_fib_config(net, cmd, &rt, &cfg); err = rtentry_to_fib_config(net, cmd, rt, &cfg);
if (err == 0) { if (err == 0) {
struct fib_table *tb; struct fib_table *tb;
......
...@@ -329,39 +329,6 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port) ...@@ -329,39 +329,6 @@ set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
sin->sin_port = 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. * Set up interface addresses and routes.
*/ */
...@@ -375,19 +342,19 @@ static int __init ic_setup_if(void) ...@@ -375,19 +342,19 @@ static int __init ic_setup_if(void)
memset(&ir, 0, sizeof(ir)); memset(&ir, 0, sizeof(ir));
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name); strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->dev->name);
set_sockaddr(sin, ic_myaddr, 0); 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", pr_err("IP-Config: Unable to set interface address (%d)\n",
err); err);
return -1; return -1;
} }
set_sockaddr(sin, ic_netmask, 0); 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", pr_err("IP-Config: Unable to set interface netmask (%d)\n",
err); err);
return -1; return -1;
} }
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); 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", pr_err("IP-Config: Unable to set interface broadcast address (%d)\n",
err); err);
return -1; return -1;
...@@ -397,11 +364,11 @@ static int __init ic_setup_if(void) ...@@ -397,11 +364,11 @@ static int __init ic_setup_if(void)
* out, we'll try to muddle along. * out, we'll try to muddle along.
*/ */
if (ic_dev_mtu != 0) { if (ic_dev_mtu != 0) {
strcpy(ir.ifr_name, ic_dev->dev->name); rtnl_lock();
ir.ifr_mtu = ic_dev_mtu; if ((err = dev_set_mtu(ic_dev->dev, ic_dev_mtu)) < 0)
if ((err = ic_dev_ioctl(SIOCSIFMTU, &ir)) < 0)
pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n", pr_err("IP-Config: Unable to set interface mtu to %d (%d)\n",
ic_dev_mtu, err); ic_dev_mtu, err);
rtnl_unlock();
} }
return 0; return 0;
} }
...@@ -423,7 +390,7 @@ static int __init ic_setup_routes(void) ...@@ -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_genmask, 0, 0);
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0); set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
rm.rt_flags = RTF_UP | RTF_GATEWAY; 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", pr_err("IP-Config: Cannot add default route (%d)\n",
err); err);
return -1; return -1;
......
This diff is collapsed.
...@@ -1035,18 +1035,23 @@ static int ioctl_standard_call(struct net_device * dev, ...@@ -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, int wext_handle_ioctl(struct net *net, unsigned int cmd, void __user *arg)
void __user *arg)
{ {
struct iw_request_info info = { .cmd = cmd, .flags = 0 }; struct iw_request_info info = { .cmd = cmd, .flags = 0 };
struct iwreq iwr;
int ret; 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_standard_call,
ioctl_private_call); ioctl_private_call);
if (ret >= 0 && if (ret >= 0 &&
IW_IS_GET(cmd) && IW_IS_GET(cmd) &&
copy_to_user(arg, iwr, sizeof(struct iwreq))) copy_to_user(arg, &iwr, sizeof(struct iwreq)))
return -EFAULT; return -EFAULT;
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment