提交 f6c90b71 编写于 作者: P Petr Vandrovec 提交者: David S. Miller

[NET]: Fix ipx/econet/appletalk/irda ioctl crashes

Fix kernel oopses whenever somebody issues compatible ioctl on AppleTalk,
Econet, IPX or IRDA socket.  For AppleTalk/Econet/IRDA it restores state
in which these sockets were before compat_ioctl was introduced to the socket
ops, for IPX it implements support for 4 ioctls which were not implemented
before - as these ioctls use structures which match between 32bit and 64bit
userspace, no special code is needed, just call 64bit ioctl handler.
Signed-off-by: NPetr Vandrovec <petr@vandrovec.name>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 f1465f7e
...@@ -1819,6 +1819,22 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1819,6 +1819,22 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc; return rc;
} }
#ifdef CONFIG_COMPAT
static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/*
* All Appletalk ioctls except SIOCATALKDIFADDR are standard. And
* SIOCATALKDIFADDR is handled by upper layer as well, so there is
* nothing to do. Eventually SIOCATALKDIFADDR should be moved
* here so there is no generic SIOCPROTOPRIVATE translation in the
* system.
*/
return -ENOIOCTLCMD;
}
#endif
static struct net_proto_family atalk_family_ops = { static struct net_proto_family atalk_family_ops = {
.family = PF_APPLETALK, .family = PF_APPLETALK,
.create = atalk_create, .create = atalk_create,
...@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { ...@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.getname = atalk_getname, .getname = atalk_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = atalk_ioctl, .ioctl = atalk_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = atalk_compat_ioctl,
#endif
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = sock_no_shutdown, .shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt, .setsockopt = sock_no_setsockopt,
......
...@@ -693,6 +693,19 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg ...@@ -693,6 +693,19 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
return 0; return 0;
} }
#ifdef CONFIG_COMPAT
static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/*
* All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec
* differs between 32bit and 64bit. Fortunately nobody in kernel uses portion
* of sockaddr which differs between 32bit and 64bit, so we do not need special
* handling.
*/
return -ENOIOCTLCMD;
}
#endif
static struct net_proto_family econet_family_ops = { static struct net_proto_family econet_family_ops = {
.family = PF_ECONET, .family = PF_ECONET,
.create = econet_create, .create = econet_create,
...@@ -710,6 +723,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { ...@@ -710,6 +723,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.getname = econet_getname, .getname = econet_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = econet_ioctl, .ioctl = econet_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = econet_compat_ioctl,
#endif
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = sock_no_shutdown, .shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt, .setsockopt = sock_no_setsockopt,
......
...@@ -1892,6 +1892,29 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1892,6 +1892,29 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return rc; return rc;
} }
#ifdef CONFIG_COMPAT
static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/*
* These 4 commands use same structure on 32bit and 64bit. Rest of IPX
* commands is handled by generic ioctl code. As these commands are
* SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
* code.
*/
switch (cmd) {
case SIOCAIPXITFCRT:
case SIOCAIPXPRISLT:
case SIOCIPXCFGDATA:
case SIOCIPXNCPCONN:
return ipx_ioctl(sock, cmd, arg);
default:
return -ENOIOCTLCMD;
}
}
#endif
/* /*
* Socket family declarations * Socket family declarations
*/ */
...@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { ...@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.getname = ipx_getname, .getname = ipx_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = ipx_ioctl, .ioctl = ipx_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ipx_compat_ioctl,
#endif
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */ .shutdown = sock_no_shutdown, /* FIXME: support shutdown */
.setsockopt = ipx_setsockopt, .setsockopt = ipx_setsockopt,
......
...@@ -1830,6 +1830,19 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1830,6 +1830,19 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return 0; return 0;
} }
#ifdef CONFIG_COMPAT
/*
* Function irda_ioctl (sock, cmd, arg)
*/
static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
/*
* All IRDA's ioctl are standard ones.
*/
return -ENOIOCTLCMD;
}
#endif
/* /*
* Function irda_setsockopt (sock, level, optname, optval, optlen) * Function irda_setsockopt (sock, level, optname, optval, optlen)
* *
...@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { ...@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.getname = irda_getname, .getname = irda_getname,
.poll = irda_poll, .poll = irda_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
#endif
.listen = irda_listen, .listen = irda_listen,
.shutdown = irda_shutdown, .shutdown = irda_shutdown,
.setsockopt = irda_setsockopt, .setsockopt = irda_setsockopt,
...@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { ...@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
#endif
.listen = irda_listen, .listen = irda_listen,
.shutdown = irda_shutdown, .shutdown = irda_shutdown,
.setsockopt = irda_setsockopt, .setsockopt = irda_setsockopt,
...@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { ...@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
#endif
.listen = irda_listen, .listen = irda_listen,
.shutdown = irda_shutdown, .shutdown = irda_shutdown,
.setsockopt = irda_setsockopt, .setsockopt = irda_setsockopt,
...@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { ...@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.getname = irda_getname, .getname = irda_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = irda_ioctl, .ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
#endif
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = irda_shutdown, .shutdown = irda_shutdown,
.setsockopt = irda_setsockopt, .setsockopt = irda_setsockopt,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册