]> git.baikalelectronics.ru Git - kernel.git/commitdiff
change semantics of ldisc ->compat_ioctl()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 14 Sep 2018 02:12:15 +0000 (22:12 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 13 Oct 2018 04:50:53 +0000 (00:50 -0400)
First of all, make it return int.  Returning long when native method
had never allowed that is ridiculous and inconvenient.

More importantly, change the caller; if ldisc ->compat_ioctl() is NULL
or returns -ENOIOCTLCMD, tty_compat_ioctl() will try to feed cmd and
compat_ptr(arg) to ldisc's native ->ioctl().

That simplifies ->compat_ioctl() instances quite a bit - they only
need to deal with ioctls that are neither generic tty ones (those
would get shunted off to tty_ioctl()) nor simple compat pointer ones.

Note that something like TCFLSH won't reach ->compat_ioctl(),
even if ldisc ->ioctl() does handle it - it will be recognized
earlier and passed to tty_ioctl() (and ultimately - ldisc ->ioctl()).

For many ldiscs it means that NULL ->compat_ioctl() does the
right thing.  Those where it won't serve (see e.g. n_r3964.c) are
also easily dealt with - we need to handle the numeric-argument
ioctls (calling the native instance) and, if such would exist,
the ioctls that need layout conversion, etc.

All in-tree ldiscs dealt with.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
drivers/bluetooth/hci_ldisc.c
drivers/input/serio/serport.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/slip/slip.c
drivers/net/wan/x25_asy.c
drivers/tty/n_gsm.c
drivers/tty/n_r3964.c
drivers/tty/tty_io.c
include/linux/tty_ldisc.h
net/nfc/nci/uart.c

index 963bb0309e25d34a44382bc3a8e9e0556cca72d1..ae0dd57a8e9963e1ecfd86d5bf3beb0e1e98abd2 100644 (file)
@@ -821,6 +821,7 @@ static int __init hci_uart_init(void)
        hci_uart_ldisc.read             = hci_uart_tty_read;
        hci_uart_ldisc.write            = hci_uart_tty_write;
        hci_uart_ldisc.ioctl            = hci_uart_tty_ioctl;
+       hci_uart_ldisc.compat_ioctl     = hci_uart_tty_ioctl;
        hci_uart_ldisc.poll             = hci_uart_tty_poll;
        hci_uart_ldisc.receive_buf      = hci_uart_tty_receive;
        hci_uart_ldisc.write_wakeup     = hci_uart_tty_wakeup;
index f8ead9f9c77eaa7737c1cf94cc1a5dc23051a858..5977b8a34ebe673364925f57d7e03275c69c24dd 100644 (file)
@@ -226,7 +226,7 @@ static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
 
 #ifdef CONFIG_COMPAT
 #define COMPAT_SPIOCSTYPE      _IOW('q', 0x01, compat_ulong_t)
-static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
+static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
                                       struct file *file,
                                       unsigned int cmd, unsigned long arg)
 {
index d79a69dd2146d347b3f44892e2534fe06290ca4a..17e6dcd2eb4248c6378439194a283ad1f93f70c6 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/semaphore.h>
-#include <linux/compat.h>
 #include <linux/refcount.h>
 
 #define SIXPACK_VERSION    "Revision: 0.3.0"
@@ -752,23 +751,6 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
        return err;
 }
 
-#ifdef CONFIG_COMPAT
-static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file,
-                               unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case SIOCGIFNAME:
-       case SIOCGIFENCAP:
-       case SIOCSIFENCAP:
-       case SIOCSIFHWADDR:
-               return sixpack_ioctl(tty, file, cmd,
-                               (unsigned long)compat_ptr(arg));
-       }
-
-       return -ENOIOCTLCMD;
-}
-#endif
-
 static struct tty_ldisc_ops sp_ldisc = {
        .owner          = THIS_MODULE,
        .magic          = TTY_LDISC_MAGIC,
@@ -776,9 +758,6 @@ static struct tty_ldisc_ops sp_ldisc = {
        .open           = sixpack_open,
        .close          = sixpack_close,
        .ioctl          = sixpack_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = sixpack_compat_ioctl,
-#endif
        .receive_buf    = sixpack_receive_buf,
        .write_wakeup   = sixpack_write_wakeup,
 };
index 13e4c1eff3536c6ab1bbc578d2a92d76c6e9027f..802233d41b25e8d167f61a825f529d5fc56b5881 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/jiffies.h>
-#include <linux/compat.h>
 
 #include <net/ax25.h>
 
@@ -875,23 +874,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
        return err;
 }
 
-#ifdef CONFIG_COMPAT
-static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case SIOCGIFNAME:
-       case SIOCGIFENCAP:
-       case SIOCSIFENCAP:
-       case SIOCSIFHWADDR:
-               return mkiss_ioctl(tty, file, cmd,
-                                  (unsigned long)compat_ptr(arg));
-       }
-
-       return -ENOIOCTLCMD;
-}
-#endif
-
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
@@ -966,9 +948,6 @@ static struct tty_ldisc_ops ax_ldisc = {
        .open           = mkiss_open,
        .close          = mkiss_close,
        .ioctl          = mkiss_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = mkiss_compat_ioctl,
-#endif
        .receive_buf    = mkiss_receive_buf,
        .write_wakeup   = mkiss_write_wakeup
 };
index b008266e91eab6cfc8fb8e009f1940ef97211e55..9757f1fc104f048f26e2463837a69a309f0853dd 100644 (file)
@@ -79,7 +79,6 @@
 #include <linux/rtnetlink.h>
 #include <linux/if_arp.h>
 #include <linux/if_slip.h>
-#include <linux/compat.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -1167,27 +1166,6 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file,
        }
 }
 
-#ifdef CONFIG_COMPAT
-static long slip_compat_ioctl(struct tty_struct *tty, struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case SIOCGIFNAME:
-       case SIOCGIFENCAP:
-       case SIOCSIFENCAP:
-       case SIOCSIFHWADDR:
-       case SIOCSKEEPALIVE:
-       case SIOCGKEEPALIVE:
-       case SIOCSOUTFILL:
-       case SIOCGOUTFILL:
-               return slip_ioctl(tty, file, cmd,
-                                 (unsigned long)compat_ptr(arg));
-       }
-
-       return -ENOIOCTLCMD;
-}
-#endif
-
 /* VSV changes start here */
 #ifdef CONFIG_SLIP_SMART
 /* function do_ioctl called from net/core/dev.c
@@ -1280,9 +1258,6 @@ static struct tty_ldisc_ops sl_ldisc = {
        .close          = slip_close,
        .hangup         = slip_hangup,
        .ioctl          = slip_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = slip_compat_ioctl,
-#endif
        .receive_buf    = slip_receive_buf,
        .write_wakeup   = slip_write_wakeup,
 };
index 74c06a5f586f7d529a0ece30a54d884e75cb903c..1098263ab862ee83003493a839d03aea477d59ea 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/lapb.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
-#include <linux/compat.h>
 #include <linux/slab.h>
 #include <net/x25device.h>
 #include "x25_asy.h"
@@ -703,21 +702,6 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
        }
 }
 
-#ifdef CONFIG_COMPAT
-static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file,
-                        unsigned int cmd,  unsigned long arg)
-{
-       switch (cmd) {
-       case SIOCGIFNAME:
-       case SIOCSIFHWADDR:
-               return x25_asy_ioctl(tty, file, cmd,
-                                    (unsigned long)compat_ptr(arg));
-       }
-
-       return -ENOIOCTLCMD;
-}
-#endif
-
 static int x25_asy_open_dev(struct net_device *dev)
 {
        struct x25_asy *sl = netdev_priv(dev);
@@ -769,9 +753,6 @@ static struct tty_ldisc_ops x25_ldisc = {
        .open           = x25_asy_open_tty,
        .close          = x25_asy_close_tty,
        .ioctl          = x25_asy_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = x25_asy_compat_ioctl,
-#endif
        .receive_buf    = x25_asy_receive_buf,
        .write_wakeup   = x25_asy_write_wakeup,
 };
index 86b7e20ffd7f1e90f1087f9212a85f201c057287..6f7da9a9d76f0a09e15b9f75067c60d954c9e6c6 100644 (file)
@@ -2614,14 +2614,6 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
        }
 }
 
-#ifdef CONFIG_COMPAT
-static long gsmld_compat_ioctl(struct tty_struct *tty, struct file *file,
-                      unsigned int cmd, unsigned long arg)
-{
-       return gsmld_ioctl(tty, file, cmd, arg);
-}
-#endif
-
 /*
  *     Network interface
  *
@@ -2833,9 +2825,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
        .flush_buffer    = gsmld_flush_buffer,
        .read            = gsmld_read,
        .write           = gsmld_write,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl    = gsmld_compat_ioctl,
-#endif
        .ioctl           = gsmld_ioctl,
        .poll            = gsmld_poll,
        .receive_buf     = gsmld_receive_buf,
index dbf1ab36758ebd6404e97a2fb0fbc4273f6c0460..749a608c40b0279d64991e937161f32ac7443158 100644 (file)
@@ -134,6 +134,10 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
                const unsigned char *buf, size_t nr);
 static int r3964_ioctl(struct tty_struct *tty, struct file *file,
                unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
+               unsigned int cmd, unsigned long arg);
+#endif
 static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
 static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
                struct poll_table_struct *wait);
@@ -149,6 +153,9 @@ static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
        .read = r3964_read,
        .write = r3964_write,
        .ioctl = r3964_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = r3964_compat_ioctl,
+#endif
        .set_termios = r3964_set_termios,
        .poll = r3964_poll,
        .receive_buf = r3964_receive_buf,
@@ -1210,6 +1217,21 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
        }
 }
 
+#ifdef CONFIG_COMPAT
+static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case R3964_ENABLE_SIGNALS:
+       case R3964_SETPRIORITY:
+       case R3964_USE_BCC:
+               return r3964_ioctl(tty, file, cmd, arg);
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+#endif
+
 static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
        TRACE_L("set_termios");
index 1a55c3e2029922d0d200389551b9cd2b36591fc0..cd8df45f09d902259a9b7edcaeef9df88aa0b0e7 100644 (file)
@@ -2824,6 +2824,9 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
                return hung_up_tty_compat_ioctl(file, cmd, arg);
        if (ld->ops->compat_ioctl)
                retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
+       if (retval == -ENOIOCTLCMD && ld->ops->ioctl)
+               retval = ld->ops->ioctl(tty, file,
+                               (unsigned long)compat_ptr(cmd), arg);
        tty_ldisc_deref(ld);
 
        return retval;
index 840894ca3fc02aeadcf22c4e41b04a3e3b09b36d..b1e6043e9917599be03a955e46ca73123827f6d6 100644 (file)
  *     low-level driver can "grab" an ioctl request before the line
  *     discpline has a chance to see it.
  *
- * long        (*compat_ioctl)(struct tty_struct * tty, struct file * file,
+ * int (*compat_ioctl)(struct tty_struct * tty, struct file * file,
  *                     unsigned int cmd, unsigned long arg);
  *
  *     Process ioctl calls from 32-bit process on 64-bit system
  *
+ *     NOTE: only ioctls that are neither "pointer to compatible
+ *     structure" nor tty-generic.  Something private that takes
+ *     an integer or a pointer to wordsize-sensitive structure
+ *     belongs here, but most of ldiscs will happily leave
+ *     it NULL.
+ *
  * void        (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  *     This function notifies the line discpline that a change has
@@ -184,7 +190,7 @@ struct tty_ldisc_ops {
                         const unsigned char *buf, size_t nr);
        int     (*ioctl)(struct tty_struct *tty, struct file *file,
                         unsigned int cmd, unsigned long arg);
-       long    (*compat_ioctl)(struct tty_struct *tty, struct file *file,
+       int     (*compat_ioctl)(struct tty_struct *tty, struct file *file,
                                unsigned int cmd, unsigned long arg);
        void    (*set_termios)(struct tty_struct *tty, struct ktermios *old);
        __poll_t (*poll)(struct tty_struct *, struct file *,
index a66f102c6c0138cf9296cb32733354a4401a7fcd..d1fa0f22c10c09b4398f505aab8ed1460c9e633f 100644 (file)
@@ -465,6 +465,7 @@ static struct tty_ldisc_ops nci_uart_ldisc = {
        .receive_buf    = nci_uart_tty_receive,
        .write_wakeup   = nci_uart_tty_wakeup,
        .ioctl          = nci_uart_tty_ioctl,
+       .compat_ioctl   = nci_uart_tty_ioctl,
 };
 
 static int __init nci_uart_init(void)