Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
44c02a2c
Commit
44c02a2c
authored
Oct 05, 2017
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dev_ioctl(): move copyin/copyout to callers
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
6a88fbe7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
71 additions
and
108 deletions
+71
-108
include/linux/netdevice.h
include/linux/netdevice.h
+2
-1
net/core/dev_ioctl.c
net/core/dev_ioctl.c
+24
-61
net/socket.c
net/socket.c
+45
-46
No files found.
include/linux/netdevice.h
View file @
44c02a2c
...
...
@@ -3315,7 +3315,8 @@ 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
*
);
...
...
net/core/dev_ioctl.c
View file @
44c02a2c
...
...
@@ -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
];
...
...
@@ -402,24 +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
;
if
(
need_copyout
)
*
need_copyout
=
true
;
if
(
cmd
==
SIOCGIFNAME
)
return
dev_ifname
(
net
,
(
struct
ifreq
__user
*
)
arg
);
if
(
copy_from_user
(
&
ifr
,
arg
,
sizeof
(
struct
ifreq
)))
return
-
EFAULT
;
return
dev_ifname
(
net
,
ifr
);
ifr
.
ifr_name
[
IFNAMSIZ
-
1
]
=
0
;
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.
*/
...
...
@@ -439,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
;
/*
...
...
@@ -477,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
;
/*
...
...
@@ -528,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
:
...
...
@@ -551,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
;
...
...
net/socket.c
View file @
44c02a2c
...
...
@@ -973,10 +973,17 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
rtnl_unlock
();
if
(
!
err
&&
copy_to_user
(
argp
,
&
ifc
,
sizeof
(
struct
ifconf
)))
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
dev_ioctl
(
net
,
cmd
,
argp
);
return
err
;
}
/*
...
...
@@ -1000,8 +1007,15 @@ 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
)
{
...
...
@@ -2695,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
;
...
...
@@ -2734,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
...
...
@@ -2773,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
;
...
...
@@ -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
)
{
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
);
if
(
put_user
(
uptr
,
&
uifr
->
ifr_settings
.
ifs_ifsu
.
raw_hdlc
))
return
-
EFAULT
;
saved
=
ifr
.
ifr_settings
.
ifs_ifsu
.
raw_hdlc
;
ifr
.
ifr_settings
.
ifs_ifsu
.
raw_hdlc
=
compat_ptr
(
uptr32
);
return
dev_ioctl
(
net
,
SIOCWANDEV
,
uifr
);
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
);
return
dev_ioctl
(
net
,
cmd
,
&
ifreq
,
NULL
);
}
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
compat_ifmap
__user
*
uifmap32
;
mm_segment_t
old_fs
;
int
err
;
uifmap32
=
&
uifr32
->
ifr_ifru
.
ifru_map
;
...
...
@@ -2879,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
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment