aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Vandrovec2006-03-27 23:39:31 -0800
committerDavid S. Miller2006-03-28 17:02:43 -0800
commitf6c90b71a355a0a4a22e1cfee5748617adc25a53 (patch)
tree2fdbe51a57e25a781128ce4a8c85375201221ded
parentf1465f7ea9e7aecba8e41d4aac9240f9b7fe2e24 (diff)
[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: Petr Vandrovec <petr@vandrovec.name> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/appletalk/ddp.c19
-rw-r--r--net/econet/af_econet.c16
-rw-r--r--net/ipx/af_ipx.c26
-rw-r--r--net/irda/af_irda.c25
4 files changed, 86 insertions, 0 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 697ac55e29dc..7b1eb9a4fc96 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1819,6 +1819,22 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
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 = {
.family = PF_APPLETALK,
.create = atalk_create,
@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.getname = atalk_getname,
.poll = datagram_poll,
.ioctl = atalk_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = atalk_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index c792994d7952..0c4c83bb2a59 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -693,6 +693,19 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
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 = {
.family = PF_ECONET,
.create = econet_create,
@@ -710,6 +723,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.getname = econet_getname,
.poll = datagram_poll,
.ioctl = econet_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = econet_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 0fb513a34d11..2dbf134d5266 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1892,6 +1892,29 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
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
*/
@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.getname = ipx_getname,
.poll = datagram_poll,
.ioctl = ipx_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ipx_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */
.setsockopt = ipx_setsockopt,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 627b11342233..2f37c9f35e27 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1830,6 +1830,19 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
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)
*
@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.getname = irda_getname,
.poll = irda_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = irda_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,
@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.getname = irda_getname,
.poll = datagram_poll,
.ioctl = irda_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = irda_compat_ioctl,
+#endif
.listen = sock_no_listen,
.shutdown = irda_shutdown,
.setsockopt = irda_setsockopt,