diff options
author | Petr Vandrovec <petr@vandrovec.name> | 2006-03-28 02:39:31 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-28 20:02:43 -0500 |
commit | f6c90b71a355a0a4a22e1cfee5748617adc25a53 (patch) | |
tree | 2fdbe51a57e25a781128ce4a8c85375201221ded /net | |
parent | f1465f7ea9e7aecba8e41d4aac9240f9b7fe2e24 (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/appletalk/ddp.c | 19 | ||||
-rw-r--r-- | net/econet/af_econet.c | 16 | ||||
-rw-r--r-- | net/ipx/af_ipx.c | 26 | ||||
-rw-r--r-- | net/irda/af_irda.c | 25 |
4 files changed, 86 insertions, 0 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 697ac55e29d..7b1eb9a4fc9 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) | |||
1819 | return rc; | 1819 | return rc; |
1820 | } | 1820 | } |
1821 | 1821 | ||
1822 | |||
1823 | #ifdef CONFIG_COMPAT | ||
1824 | static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1825 | { | ||
1826 | /* | ||
1827 | * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And | ||
1828 | * SIOCATALKDIFADDR is handled by upper layer as well, so there is | ||
1829 | * nothing to do. Eventually SIOCATALKDIFADDR should be moved | ||
1830 | * here so there is no generic SIOCPROTOPRIVATE translation in the | ||
1831 | * system. | ||
1832 | */ | ||
1833 | return -ENOIOCTLCMD; | ||
1834 | } | ||
1835 | #endif | ||
1836 | |||
1837 | |||
1822 | static struct net_proto_family atalk_family_ops = { | 1838 | static struct net_proto_family atalk_family_ops = { |
1823 | .family = PF_APPLETALK, | 1839 | .family = PF_APPLETALK, |
1824 | .create = atalk_create, | 1840 | .create = atalk_create, |
@@ -1836,6 +1852,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | |||
1836 | .getname = atalk_getname, | 1852 | .getname = atalk_getname, |
1837 | .poll = datagram_poll, | 1853 | .poll = datagram_poll, |
1838 | .ioctl = atalk_ioctl, | 1854 | .ioctl = atalk_ioctl, |
1855 | #ifdef CONFIG_COMPAT | ||
1856 | .compat_ioctl = atalk_compat_ioctl, | ||
1857 | #endif | ||
1839 | .listen = sock_no_listen, | 1858 | .listen = sock_no_listen, |
1840 | .shutdown = sock_no_shutdown, | 1859 | .shutdown = sock_no_shutdown, |
1841 | .setsockopt = sock_no_setsockopt, | 1860 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index c792994d795..0c4c83bb2a5 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 | |||
693 | return 0; | 693 | return 0; |
694 | } | 694 | } |
695 | 695 | ||
696 | #ifdef CONFIG_COMPAT | ||
697 | static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
698 | { | ||
699 | /* | ||
700 | * All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec | ||
701 | * differs between 32bit and 64bit. Fortunately nobody in kernel uses portion | ||
702 | * of sockaddr which differs between 32bit and 64bit, so we do not need special | ||
703 | * handling. | ||
704 | */ | ||
705 | return -ENOIOCTLCMD; | ||
706 | } | ||
707 | #endif | ||
708 | |||
696 | static struct net_proto_family econet_family_ops = { | 709 | static struct net_proto_family econet_family_ops = { |
697 | .family = PF_ECONET, | 710 | .family = PF_ECONET, |
698 | .create = econet_create, | 711 | .create = econet_create, |
@@ -710,6 +723,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { | |||
710 | .getname = econet_getname, | 723 | .getname = econet_getname, |
711 | .poll = datagram_poll, | 724 | .poll = datagram_poll, |
712 | .ioctl = econet_ioctl, | 725 | .ioctl = econet_ioctl, |
726 | #ifdef CONFIG_COMPAT | ||
727 | .compat_ioctl = econet_compat_ioctl, | ||
728 | #endif | ||
713 | .listen = sock_no_listen, | 729 | .listen = sock_no_listen, |
714 | .shutdown = sock_no_shutdown, | 730 | .shutdown = sock_no_shutdown, |
715 | .setsockopt = sock_no_setsockopt, | 731 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 0fb513a34d1..2dbf134d526 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) | |||
1892 | return rc; | 1892 | return rc; |
1893 | } | 1893 | } |
1894 | 1894 | ||
1895 | |||
1896 | #ifdef CONFIG_COMPAT | ||
1897 | static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1898 | { | ||
1899 | /* | ||
1900 | * These 4 commands use same structure on 32bit and 64bit. Rest of IPX | ||
1901 | * commands is handled by generic ioctl code. As these commands are | ||
1902 | * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic | ||
1903 | * code. | ||
1904 | */ | ||
1905 | switch (cmd) { | ||
1906 | case SIOCAIPXITFCRT: | ||
1907 | case SIOCAIPXPRISLT: | ||
1908 | case SIOCIPXCFGDATA: | ||
1909 | case SIOCIPXNCPCONN: | ||
1910 | return ipx_ioctl(sock, cmd, arg); | ||
1911 | default: | ||
1912 | return -ENOIOCTLCMD; | ||
1913 | } | ||
1914 | } | ||
1915 | #endif | ||
1916 | |||
1917 | |||
1895 | /* | 1918 | /* |
1896 | * Socket family declarations | 1919 | * Socket family declarations |
1897 | */ | 1920 | */ |
@@ -1913,6 +1936,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { | |||
1913 | .getname = ipx_getname, | 1936 | .getname = ipx_getname, |
1914 | .poll = datagram_poll, | 1937 | .poll = datagram_poll, |
1915 | .ioctl = ipx_ioctl, | 1938 | .ioctl = ipx_ioctl, |
1939 | #ifdef CONFIG_COMPAT | ||
1940 | .compat_ioctl = ipx_compat_ioctl, | ||
1941 | #endif | ||
1916 | .listen = sock_no_listen, | 1942 | .listen = sock_no_listen, |
1917 | .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ | 1943 | .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ |
1918 | .setsockopt = ipx_setsockopt, | 1944 | .setsockopt = ipx_setsockopt, |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 627b1134223..2f37c9f35e2 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) | |||
1830 | return 0; | 1830 | return 0; |
1831 | } | 1831 | } |
1832 | 1832 | ||
1833 | #ifdef CONFIG_COMPAT | ||
1834 | /* | ||
1835 | * Function irda_ioctl (sock, cmd, arg) | ||
1836 | */ | ||
1837 | static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1838 | { | ||
1839 | /* | ||
1840 | * All IRDA's ioctl are standard ones. | ||
1841 | */ | ||
1842 | return -ENOIOCTLCMD; | ||
1843 | } | ||
1844 | #endif | ||
1845 | |||
1833 | /* | 1846 | /* |
1834 | * Function irda_setsockopt (sock, level, optname, optval, optlen) | 1847 | * Function irda_setsockopt (sock, level, optname, optval, optlen) |
1835 | * | 1848 | * |
@@ -2476,6 +2489,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { | |||
2476 | .getname = irda_getname, | 2489 | .getname = irda_getname, |
2477 | .poll = irda_poll, | 2490 | .poll = irda_poll, |
2478 | .ioctl = irda_ioctl, | 2491 | .ioctl = irda_ioctl, |
2492 | #ifdef CONFIG_COMPAT | ||
2493 | .compat_ioctl = irda_compat_ioctl, | ||
2494 | #endif | ||
2479 | .listen = irda_listen, | 2495 | .listen = irda_listen, |
2480 | .shutdown = irda_shutdown, | 2496 | .shutdown = irda_shutdown, |
2481 | .setsockopt = irda_setsockopt, | 2497 | .setsockopt = irda_setsockopt, |
@@ -2497,6 +2513,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { | |||
2497 | .getname = irda_getname, | 2513 | .getname = irda_getname, |
2498 | .poll = datagram_poll, | 2514 | .poll = datagram_poll, |
2499 | .ioctl = irda_ioctl, | 2515 | .ioctl = irda_ioctl, |
2516 | #ifdef CONFIG_COMPAT | ||
2517 | .compat_ioctl = irda_compat_ioctl, | ||
2518 | #endif | ||
2500 | .listen = irda_listen, | 2519 | .listen = irda_listen, |
2501 | .shutdown = irda_shutdown, | 2520 | .shutdown = irda_shutdown, |
2502 | .setsockopt = irda_setsockopt, | 2521 | .setsockopt = irda_setsockopt, |
@@ -2518,6 +2537,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { | |||
2518 | .getname = irda_getname, | 2537 | .getname = irda_getname, |
2519 | .poll = datagram_poll, | 2538 | .poll = datagram_poll, |
2520 | .ioctl = irda_ioctl, | 2539 | .ioctl = irda_ioctl, |
2540 | #ifdef CONFIG_COMPAT | ||
2541 | .compat_ioctl = irda_compat_ioctl, | ||
2542 | #endif | ||
2521 | .listen = irda_listen, | 2543 | .listen = irda_listen, |
2522 | .shutdown = irda_shutdown, | 2544 | .shutdown = irda_shutdown, |
2523 | .setsockopt = irda_setsockopt, | 2545 | .setsockopt = irda_setsockopt, |
@@ -2540,6 +2562,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { | |||
2540 | .getname = irda_getname, | 2562 | .getname = irda_getname, |
2541 | .poll = datagram_poll, | 2563 | .poll = datagram_poll, |
2542 | .ioctl = irda_ioctl, | 2564 | .ioctl = irda_ioctl, |
2565 | #ifdef CONFIG_COMPAT | ||
2566 | .compat_ioctl = irda_compat_ioctl, | ||
2567 | #endif | ||
2543 | .listen = sock_no_listen, | 2568 | .listen = sock_no_listen, |
2544 | .shutdown = irda_shutdown, | 2569 | .shutdown = irda_shutdown, |
2545 | .setsockopt = irda_setsockopt, | 2570 | .setsockopt = irda_setsockopt, |