18
18
* match. --pb
19
19
*/
20
20
21
- static int dev_ifname (struct net * net , struct ifreq __user * arg )
21
+ static int dev_ifname (struct net * net , struct ifreq * ifr )
22
22
{
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 );
41
25
}
42
26
43
27
static gifconf_func_t * gifconf_list [NPROTO ];
@@ -66,9 +50,8 @@ EXPORT_SYMBOL(register_gifconf);
66
50
* Thus we will need a 'compatibility mode'.
67
51
*/
68
52
69
- static int dev_ifconf (struct net * net , char __user * arg )
53
+ int dev_ifconf (struct net * net , struct ifconf * ifc , int size )
70
54
{
71
- struct ifconf ifc ;
72
55
struct net_device * dev ;
73
56
char __user * pos ;
74
57
int len ;
@@ -79,11 +62,8 @@ static int dev_ifconf(struct net *net, char __user *arg)
79
62
* Fetch the caller's info block.
80
63
*/
81
64
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 ;
87
67
88
68
/*
89
69
* 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
75
if (gifconf_list [i ]) {
96
76
int done ;
97
77
if (!pos )
98
- done = gifconf_list [i ](dev , NULL , 0 );
78
+ done = gifconf_list [i ](dev , NULL , 0 , size );
99
79
else
100
80
done = gifconf_list [i ](dev , pos + total ,
101
- len - total );
81
+ len - total , size );
102
82
if (done < 0 )
103
83
return - EFAULT ;
104
84
total += done ;
@@ -109,12 +89,12 @@ static int dev_ifconf(struct net *net, char __user *arg)
109
89
/*
110
90
* All done. Write the updated control block back to the caller.
111
91
*/
112
- ifc . ifc_len = total ;
92
+ ifc -> ifc_len = total ;
113
93
114
94
/*
115
95
* Both BSD and Solaris return 0 here, so we do too.
116
96
*/
117
- return copy_to_user ( arg , & ifc , sizeof ( struct ifconf )) ? - EFAULT : 0 ;
97
+ return 0 ;
118
98
}
119
99
120
100
/*
@@ -406,53 +386,24 @@ EXPORT_SYMBOL(dev_load);
406
386
* positive or a negative errno code on error.
407
387
*/
408
388
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 )
410
390
{
411
- struct ifreq ifr ;
412
391
int ret ;
413
392
char * colon ;
414
393
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;
426
396
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 );
443
398
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 ;
451
400
452
- colon = strchr (ifr . ifr_name , ':' );
401
+ colon = strchr (ifr -> ifr_name , ':' );
453
402
if (colon )
454
403
* colon = 0 ;
455
404
405
+ dev_load (net , ifr -> ifr_name );
406
+
456
407
/*
457
408
* See which interface the caller is talking about.
458
409
*/
@@ -472,31 +423,19 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
472
423
case SIOCGIFMAP :
473
424
case SIOCGIFINDEX :
474
425
case SIOCGIFTXQLEN :
475
- dev_load (net , ifr .ifr_name );
476
426
rcu_read_lock ();
477
- ret = dev_ifsioc_locked (net , & ifr , cmd );
427
+ ret = dev_ifsioc_locked (net , ifr , cmd );
478
428
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 = ':' ;
486
431
return ret ;
487
432
488
433
case SIOCETHTOOL :
489
- dev_load (net , ifr .ifr_name );
490
434
rtnl_lock ();
491
- ret = dev_ethtool (net , & ifr );
435
+ ret = dev_ethtool (net , ifr );
492
436
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 = ':' ;
500
439
return ret ;
501
440
502
441
/*
@@ -510,17 +449,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
510
449
case SIOCSIFNAME :
511
450
if (!ns_capable (net -> user_ns , CAP_NET_ADMIN ))
512
451
return - EPERM ;
513
- dev_load (net , ifr .ifr_name );
514
452
rtnl_lock ();
515
- ret = dev_ifsioc (net , & ifr , cmd );
453
+ ret = dev_ifsioc (net , ifr , cmd );
516
454
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 = ':' ;
524
457
return ret ;
525
458
526
459
/*
@@ -561,10 +494,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
561
494
/* fall through */
562
495
case SIOCBONDSLAVEINFOQUERY :
563
496
case SIOCBONDINFOQUERY :
564
- dev_load (net , ifr .ifr_name );
565
497
rtnl_lock ();
566
- ret = dev_ifsioc (net , & ifr , cmd );
498
+ ret = dev_ifsioc (net , ifr , cmd );
567
499
rtnl_unlock ();
500
+ if (need_copyout )
501
+ * need_copyout = false;
568
502
return ret ;
569
503
570
504
case SIOCGIFMEM :
@@ -584,13 +518,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
584
518
cmd == SIOCGHWTSTAMP ||
585
519
(cmd >= SIOCDEVPRIVATE &&
586
520
cmd <= SIOCDEVPRIVATE + 15 )) {
587
- dev_load (net , ifr .ifr_name );
588
521
rtnl_lock ();
589
- ret = dev_ifsioc (net , & ifr , cmd );
522
+ ret = dev_ifsioc (net , ifr , cmd );
590
523
rtnl_unlock ();
591
- if (!ret && copy_to_user (arg , & ifr ,
592
- sizeof (struct ifreq )))
593
- ret = - EFAULT ;
594
524
return ret ;
595
525
}
596
526
return - ENOTTY ;
0 commit comments