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 | |
| 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>
| -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 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) | |||
| 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 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 | |||
| 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 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) | |||
| 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 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) | |||
| 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, |
