* [PATCH] socket: fix struct ifreq size in compat ioctl
@ 2018-09-13 11:49 Johannes Berg
2018-09-13 12:13 ` Al Viro
2018-09-13 22:48 ` kbuild test robot
0 siblings, 2 replies; 4+ messages in thread
From: Johannes Berg @ 2018-09-13 11:49 UTC (permalink / raw)
To: netdev; +Cc: Robert O'Callahan, Al Viro, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
As reported by Reobert O'Callahan, since Viro's commit to kill
dev_ifsioc() we attempt to copy too much data in compat mode,
which may lead to EFAULT when the 32-bit version of struct ifreq
sits at/near the end of a page boundary, and the next page isn't
mapped.
Fix this by passing whether or not we're doing a compat call and
copying the appropriate size in/out, as we did before. This works
because only the embedded "struct ifmap" has different size, and
this is only used in SIOCGIFMAP/SIOCSIFMAP which has a different
handler. All other parts of the union are naturally compatible.
Fixes: bf4405737f9f ("kill dev_ifsioc()")
Reported-by: Robert O'Callahan <robert@ocallahan.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/socket.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index e6945e318f02..cef0725a2aaf 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -941,7 +941,8 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
EXPORT_SYMBOL(dlci_ioctl_set);
static long sock_do_ioctl(struct net *net, struct socket *sock,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg,
+ bool compat)
{
int err;
void __user *argp = (void __user *)arg;
@@ -967,11 +968,15 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
} else {
struct ifreq ifr;
bool need_copyout;
- if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
+ if (copy_from_user(&ifr, argp,
+ compat ? sizeof(struct compat_ifreq) :
+ 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)))
+ if (copy_to_user(argp, &ifr,
+ compat ? sizeof(struct compat_ifreq) :
+ sizeof(struct ifreq)))
return -EFAULT;
}
return err;
@@ -1070,7 +1075,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
err = open_related_ns(&net->ns, get_net_ns);
break;
default:
- err = sock_do_ioctl(net, sock, cmd, arg);
+ err = sock_do_ioctl(net, sock, cmd, arg, false);
break;
}
return err;
@@ -2750,7 +2755,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
int err;
set_fs(KERNEL_DS);
- err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
+ err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv, true);
set_fs(old_fs);
if (!err)
err = compat_put_timeval(&ktv, up);
@@ -2766,7 +2771,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
int err;
set_fs(KERNEL_DS);
- err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
+ err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts, true);
set_fs(old_fs);
if (!err)
err = compat_put_timespec(&kts, up);
@@ -3072,7 +3077,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
}
set_fs(KERNEL_DS);
- ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
+ ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r, true);
set_fs(old_fs);
out:
@@ -3185,7 +3190,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCBONDSETHWADDR:
case SIOCBONDCHANGEACTIVE:
case SIOCGIFNAME:
- return sock_do_ioctl(net, sock, cmd, arg);
+ return sock_do_ioctl(net, sock, cmd, arg, true);
}
return -ENOIOCTLCMD;
--
2.14.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] socket: fix struct ifreq size in compat ioctl
2018-09-13 11:49 [PATCH] socket: fix struct ifreq size in compat ioctl Johannes Berg
@ 2018-09-13 12:13 ` Al Viro
2018-09-13 12:16 ` Johannes Berg
2018-09-13 22:48 ` kbuild test robot
1 sibling, 1 reply; 4+ messages in thread
From: Al Viro @ 2018-09-13 12:13 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, Robert O'Callahan, Johannes Berg
On Thu, Sep 13, 2018 at 01:49:09PM +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> As reported by Reobert O'Callahan, since Viro's commit to kill
> dev_ifsioc() we attempt to copy too much data in compat mode,
> which may lead to EFAULT when the 32-bit version of struct ifreq
> sits at/near the end of a page boundary, and the next page isn't
> mapped.
>
> Fix this by passing whether or not we're doing a compat call and
> copying the appropriate size in/out, as we did before. This works
> because only the embedded "struct ifmap" has different size, and
> this is only used in SIOCGIFMAP/SIOCSIFMAP which has a different
> handler. All other parts of the union are naturally compatible.
Might be better to pass explicit size instead of this bool compat...
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] socket: fix struct ifreq size in compat ioctl
2018-09-13 12:13 ` Al Viro
@ 2018-09-13 12:16 ` Johannes Berg
0 siblings, 0 replies; 4+ messages in thread
From: Johannes Berg @ 2018-09-13 12:16 UTC (permalink / raw)
To: Al Viro; +Cc: netdev, Robert O'Callahan
On Thu, 2018-09-13 at 13:13 +0100, Al Viro wrote:
> On Thu, Sep 13, 2018 at 01:49:09PM +0200, Johannes Berg wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> >
> > As reported by Reobert O'Callahan, since Viro's commit to kill
> > dev_ifsioc() we attempt to copy too much data in compat mode,
> > which may lead to EFAULT when the 32-bit version of struct ifreq
> > sits at/near the end of a page boundary, and the next page isn't
> > mapped.
> >
> > Fix this by passing whether or not we're doing a compat call and
> > copying the appropriate size in/out, as we did before. This works
> > because only the embedded "struct ifmap" has different size, and
> > this is only used in SIOCGIFMAP/SIOCSIFMAP which has a different
> > handler. All other parts of the union are naturally compatible.
>
> Might be better to pass explicit size instead of this bool compat...
Yeah, that's a bit better perhaps, I should resend to have the bugzilla
link anyway.
johannes
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] socket: fix struct ifreq size in compat ioctl
2018-09-13 11:49 [PATCH] socket: fix struct ifreq size in compat ioctl Johannes Berg
2018-09-13 12:13 ` Al Viro
@ 2018-09-13 22:48 ` kbuild test robot
1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2018-09-13 22:48 UTC (permalink / raw)
To: Johannes Berg
Cc: kbuild-all, netdev, Robert O'Callahan, Al Viro, Johannes Berg
[-- Attachment #1: Type: text/plain, Size: 2550 bytes --]
Hi Johannes,
I love your patch! Yet something to improve:
[auto build test ERROR on net/master]
[also build test ERROR on v4.19-rc3 next-20180913]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Johannes-Berg/socket-fix-struct-ifreq-size-in-compat-ioctl/20180914-061826
config: x86_64-randconfig-x013-201836 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
net/socket.c: In function 'sock_do_ioctl':
>> net/socket.c:972:24: error: invalid application of 'sizeof' to incomplete type 'struct compat_ifreq'
compat ? sizeof(struct compat_ifreq) :
^~~~~~
net/socket.c:978:23: error: invalid application of 'sizeof' to incomplete type 'struct compat_ifreq'
compat ? sizeof(struct compat_ifreq) :
^~~~~~
vim +972 net/socket.c
942
943 static long sock_do_ioctl(struct net *net, struct socket *sock,
944 unsigned int cmd, unsigned long arg,
945 bool compat)
946 {
947 int err;
948 void __user *argp = (void __user *)arg;
949
950 err = sock->ops->ioctl(sock, cmd, arg);
951
952 /*
953 * If this ioctl is unknown try to hand it down
954 * to the NIC driver.
955 */
956 if (err != -ENOIOCTLCMD)
957 return err;
958
959 if (cmd == SIOCGIFCONF) {
960 struct ifconf ifc;
961 if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
962 return -EFAULT;
963 rtnl_lock();
964 err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
965 rtnl_unlock();
966 if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
967 err = -EFAULT;
968 } else {
969 struct ifreq ifr;
970 bool need_copyout;
971 if (copy_from_user(&ifr, argp,
> 972 compat ? sizeof(struct compat_ifreq) :
973 sizeof(struct ifreq)))
974 return -EFAULT;
975 err = dev_ioctl(net, cmd, &ifr, &need_copyout);
976 if (!err && need_copyout)
977 if (copy_to_user(argp, &ifr,
978 compat ? sizeof(struct compat_ifreq) :
979 sizeof(struct ifreq)))
980 return -EFAULT;
981 }
982 return err;
983 }
984
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28962 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-09-14 4:00 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-09-13 11:49 [PATCH] socket: fix struct ifreq size in compat ioctl Johannes Berg
2018-09-13 12:13 ` Al Viro
2018-09-13 12:16 ` Johannes Berg
2018-09-13 22:48 ` kbuild test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).