Skip to content

Commit 8ec59b4

Browse files
committed
Merge branch 'rebased-net-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Signed-off-by: David S. Miller <[email protected]>
2 parents 955bd1d + 5c59e56 commit 8ec59b4

File tree

12 files changed

+173
-399
lines changed

12 files changed

+173
-399
lines changed

include/linux/inetdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
173173
}
174174

175175
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
176-
int devinet_ioctl(struct net *net, unsigned int cmd, void __user *);
176+
int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *);
177177
void devinet_init(void);
178178
struct in_device *inetdev_by_index(struct net *, int);
179179
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);

include/linux/net.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ int kernel_sendpage(struct socket *sock, struct page *page, int offset,
306306
size_t size, int flags);
307307
int kernel_sendpage_locked(struct sock *sk, struct page *page, int offset,
308308
size_t size, int flags);
309-
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
310309
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
311310

312311
/* Routine returns the IP overhead imposed by a (caller-protected) socket. */

include/linux/netdevice.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2761,7 +2761,8 @@ static inline bool dev_validate_header(const struct net_device *dev,
27612761
return false;
27622762
}
27632763

2764-
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
2764+
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr,
2765+
int len, int size);
27652766
int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
27662767
static inline int unregister_gifconf(unsigned int family)
27672768
{
@@ -3314,7 +3315,9 @@ int netdev_rx_handler_register(struct net_device *dev,
33143315
void netdev_rx_handler_unregister(struct net_device *dev);
33153316

33163317
bool dev_valid_name(const char *name);
3317-
int dev_ioctl(struct net *net, unsigned int cmd, void __user *);
3318+
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
3319+
bool *need_copyout);
3320+
int dev_ifconf(struct net *net, struct ifconf *, int);
33183321
int dev_ethtool(struct net *net, struct ifreq *);
33193322
unsigned int dev_get_flags(const struct net_device *);
33203323
int __dev_change_flags(struct net_device *, unsigned int flags);

include/net/route.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ unsigned int inet_addr_type_dev_table(struct net *net,
217217
const struct net_device *dev,
218218
__be32 addr);
219219
void ip_rt_multicast_event(struct in_device *);
220-
int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
220+
int ip_rt_ioctl(struct net *, unsigned int cmd, struct rtentry *rt);
221221
void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
222222
struct rtable *rt_dst_alloc(struct net_device *dev,
223223
unsigned int flags, u16 type,

include/net/wext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
struct net;
88

99
#ifdef CONFIG_WEXT_CORE
10-
int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
10+
int wext_handle_ioctl(struct net *net, unsigned int cmd,
1111
void __user *arg);
1212
int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
1313
unsigned long arg);
1414

1515
struct iw_statistics *get_wireless_stats(struct net_device *dev);
1616
int call_commit_handler(struct net_device *dev);
1717
#else
18-
static inline int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
18+
static inline int wext_handle_ioctl(struct net *net, unsigned int cmd,
1919
void __user *arg)
2020
{
2121
return -EINVAL;

net/core/dev_ioctl.c

Lines changed: 31 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,10 @@
1818
* match. --pb
1919
*/
2020

21-
static int dev_ifname(struct net *net, struct ifreq __user *arg)
21+
static int dev_ifname(struct net *net, struct ifreq *ifr)
2222
{
23-
struct ifreq ifr;
24-
int error;
25-
26-
/*
27-
* Fetch the caller's info block.
28-
*/
29-
30-
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
31-
return -EFAULT;
32-
ifr.ifr_name[IFNAMSIZ-1] = 0;
33-
34-
error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex);
35-
if (error)
36-
return error;
37-
38-
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
39-
return -EFAULT;
40-
return 0;
23+
ifr->ifr_name[IFNAMSIZ-1] = 0;
24+
return netdev_get_name(net, ifr->ifr_name, ifr->ifr_ifindex);
4125
}
4226

4327
static gifconf_func_t *gifconf_list[NPROTO];
@@ -66,9 +50,8 @@ EXPORT_SYMBOL(register_gifconf);
6650
* Thus we will need a 'compatibility mode'.
6751
*/
6852

69-
static int dev_ifconf(struct net *net, char __user *arg)
53+
int dev_ifconf(struct net *net, struct ifconf *ifc, int size)
7054
{
71-
struct ifconf ifc;
7255
struct net_device *dev;
7356
char __user *pos;
7457
int len;
@@ -79,11 +62,8 @@ static int dev_ifconf(struct net *net, char __user *arg)
7962
* Fetch the caller's info block.
8063
*/
8164

82-
if (copy_from_user(&ifc, arg, sizeof(struct ifconf)))
83-
return -EFAULT;
84-
85-
pos = ifc.ifc_buf;
86-
len = ifc.ifc_len;
65+
pos = ifc->ifc_buf;
66+
len = ifc->ifc_len;
8767

8868
/*
8969
* 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)
9575
if (gifconf_list[i]) {
9676
int done;
9777
if (!pos)
98-
done = gifconf_list[i](dev, NULL, 0);
78+
done = gifconf_list[i](dev, NULL, 0, size);
9979
else
10080
done = gifconf_list[i](dev, pos + total,
101-
len - total);
81+
len - total, size);
10282
if (done < 0)
10383
return -EFAULT;
10484
total += done;
@@ -109,12 +89,12 @@ static int dev_ifconf(struct net *net, char __user *arg)
10989
/*
11090
* All done. Write the updated control block back to the caller.
11191
*/
112-
ifc.ifc_len = total;
92+
ifc->ifc_len = total;
11393

11494
/*
11595
* Both BSD and Solaris return 0 here, so we do too.
11696
*/
117-
return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0;
97+
return 0;
11898
}
11999

120100
/*
@@ -406,53 +386,24 @@ EXPORT_SYMBOL(dev_load);
406386
* positive or a negative errno code on error.
407387
*/
408388

409-
int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
389+
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
410390
{
411-
struct ifreq ifr;
412391
int ret;
413392
char *colon;
414393

415-
/* One special case: SIOCGIFCONF takes ifconf argument
416-
and requires shared lock, because it sleeps writing
417-
to user space.
418-
*/
419-
420-
if (cmd == SIOCGIFCONF) {
421-
rtnl_lock();
422-
ret = dev_ifconf(net, (char __user *) arg);
423-
rtnl_unlock();
424-
return ret;
425-
}
394+
if (need_copyout)
395+
*need_copyout = true;
426396
if (cmd == SIOCGIFNAME)
427-
return dev_ifname(net, (struct ifreq __user *)arg);
428-
429-
/*
430-
* Take care of Wireless Extensions. Unfortunately struct iwreq
431-
* isn't a proper subset of struct ifreq (it's 8 byte shorter)
432-
* so we need to treat it specially, otherwise applications may
433-
* fault if the struct they're passing happens to land at the
434-
* end of a mapped page.
435-
*/
436-
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
437-
struct iwreq iwr;
438-
439-
if (copy_from_user(&iwr, arg, sizeof(iwr)))
440-
return -EFAULT;
441-
442-
iwr.ifr_name[sizeof(iwr.ifr_name) - 1] = 0;
397+
return dev_ifname(net, ifr);
443398

444-
return wext_handle_ioctl(net, &iwr, cmd, arg);
445-
}
446-
447-
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
448-
return -EFAULT;
449-
450-
ifr.ifr_name[IFNAMSIZ-1] = 0;
399+
ifr->ifr_name[IFNAMSIZ-1] = 0;
451400

452-
colon = strchr(ifr.ifr_name, ':');
401+
colon = strchr(ifr->ifr_name, ':');
453402
if (colon)
454403
*colon = 0;
455404

405+
dev_load(net, ifr->ifr_name);
406+
456407
/*
457408
* See which interface the caller is talking about.
458409
*/
@@ -472,31 +423,19 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
472423
case SIOCGIFMAP:
473424
case SIOCGIFINDEX:
474425
case SIOCGIFTXQLEN:
475-
dev_load(net, ifr.ifr_name);
476426
rcu_read_lock();
477-
ret = dev_ifsioc_locked(net, &ifr, cmd);
427+
ret = dev_ifsioc_locked(net, ifr, cmd);
478428
rcu_read_unlock();
479-
if (!ret) {
480-
if (colon)
481-
*colon = ':';
482-
if (copy_to_user(arg, &ifr,
483-
sizeof(struct ifreq)))
484-
ret = -EFAULT;
485-
}
429+
if (colon)
430+
*colon = ':';
486431
return ret;
487432

488433
case SIOCETHTOOL:
489-
dev_load(net, ifr.ifr_name);
490434
rtnl_lock();
491-
ret = dev_ethtool(net, &ifr);
435+
ret = dev_ethtool(net, ifr);
492436
rtnl_unlock();
493-
if (!ret) {
494-
if (colon)
495-
*colon = ':';
496-
if (copy_to_user(arg, &ifr,
497-
sizeof(struct ifreq)))
498-
ret = -EFAULT;
499-
}
437+
if (colon)
438+
*colon = ':';
500439
return ret;
501440

502441
/*
@@ -510,17 +449,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
510449
case SIOCSIFNAME:
511450
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
512451
return -EPERM;
513-
dev_load(net, ifr.ifr_name);
514452
rtnl_lock();
515-
ret = dev_ifsioc(net, &ifr, cmd);
453+
ret = dev_ifsioc(net, ifr, cmd);
516454
rtnl_unlock();
517-
if (!ret) {
518-
if (colon)
519-
*colon = ':';
520-
if (copy_to_user(arg, &ifr,
521-
sizeof(struct ifreq)))
522-
ret = -EFAULT;
523-
}
455+
if (colon)
456+
*colon = ':';
524457
return ret;
525458

526459
/*
@@ -561,10 +494,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
561494
/* fall through */
562495
case SIOCBONDSLAVEINFOQUERY:
563496
case SIOCBONDINFOQUERY:
564-
dev_load(net, ifr.ifr_name);
565497
rtnl_lock();
566-
ret = dev_ifsioc(net, &ifr, cmd);
498+
ret = dev_ifsioc(net, ifr, cmd);
567499
rtnl_unlock();
500+
if (need_copyout)
501+
*need_copyout = false;
568502
return ret;
569503

570504
case SIOCGIFMEM:
@@ -584,13 +518,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
584518
cmd == SIOCGHWTSTAMP ||
585519
(cmd >= SIOCDEVPRIVATE &&
586520
cmd <= SIOCDEVPRIVATE + 15)) {
587-
dev_load(net, ifr.ifr_name);
588521
rtnl_lock();
589-
ret = dev_ifsioc(net, &ifr, cmd);
522+
ret = dev_ifsioc(net, ifr, cmd);
590523
rtnl_unlock();
591-
if (!ret && copy_to_user(arg, &ifr,
592-
sizeof(struct ifreq)))
593-
ret = -EFAULT;
594524
return ret;
595525
}
596526
return -ENOTTY;

net/ipv4/af_inet.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
872872
struct sock *sk = sock->sk;
873873
int err = 0;
874874
struct net *net = sock_net(sk);
875+
void __user *p = (void __user *)arg;
876+
struct ifreq ifr;
877+
struct rtentry rt;
875878

876879
switch (cmd) {
877880
case SIOCGSTAMP:
@@ -882,26 +885,39 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
882885
break;
883886
case SIOCADDRT:
884887
case SIOCDELRT:
888+
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
889+
return -EFAULT;
890+
err = ip_rt_ioctl(net, cmd, &rt);
891+
break;
885892
case SIOCRTMSG:
886-
err = ip_rt_ioctl(net, cmd, (void __user *)arg);
893+
err = -EINVAL;
887894
break;
888895
case SIOCDARP:
889896
case SIOCGARP:
890897
case SIOCSARP:
891898
err = arp_ioctl(net, cmd, (void __user *)arg);
892899
break;
893900
case SIOCGIFADDR:
894-
case SIOCSIFADDR:
895901
case SIOCGIFBRDADDR:
896-
case SIOCSIFBRDADDR:
897902
case SIOCGIFNETMASK:
898-
case SIOCSIFNETMASK:
899903
case SIOCGIFDSTADDR:
904+
case SIOCGIFPFLAGS:
905+
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
906+
return -EFAULT;
907+
err = devinet_ioctl(net, cmd, &ifr);
908+
if (!err && copy_to_user(p, &ifr, sizeof(struct ifreq)))
909+
err = -EFAULT;
910+
break;
911+
912+
case SIOCSIFADDR:
913+
case SIOCSIFBRDADDR:
914+
case SIOCSIFNETMASK:
900915
case SIOCSIFDSTADDR:
901916
case SIOCSIFPFLAGS:
902-
case SIOCGIFPFLAGS:
903917
case SIOCSIFFLAGS:
904-
err = devinet_ioctl(net, cmd, (void __user *)arg);
918+
if (copy_from_user(&ifr, p, sizeof(struct ifreq)))
919+
return -EFAULT;
920+
err = devinet_ioctl(net, cmd, &ifr);
905921
break;
906922
default:
907923
if (sk->sk_prot->ioctl)

0 commit comments

Comments
 (0)