]> err.no Git - linux-2.6/commitdiff
tty: add compat_ioctl
authorPaul Fulghum <paulkf@microgate.com>
Fri, 11 May 2007 05:22:50 +0000 (22:22 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 11 May 2007 15:29:35 +0000 (08:29 -0700)
Add compat_ioctl method for tty code to allow processing of 32 bit ioctl
calls on 64 bit systems by tty core, tty drivers, and line disciplines.

Based on patch by Arnd Bergmann:
http://www.uwsg.iu.edu/hypermail/linux/kernel/0511.0/1732.html

[akpm@linux-foundation.org: make things static]
Signed-off-by: Paul Fulghum <paulkf@microgate.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/n_tty.c
drivers/char/tty_io.c
include/linux/tty_driver.h
include/linux/tty_ldisc.h

index 6ac3ca4c723c2c660c5d084b9c7834035767fbb5..b3d4ccc33a47e777d1a391ae9a85bde2f450051e 100644 (file)
@@ -1544,21 +1544,18 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol
 }
 
 struct tty_ldisc tty_ldisc_N_TTY = {
-       TTY_LDISC_MAGIC,        /* magic */
-       "n_tty",                /* name */
-       0,                      /* num */
-       0,                      /* flags */
-       n_tty_open,             /* open */
-       n_tty_close,            /* close */
-       n_tty_flush_buffer,     /* flush_buffer */
-       n_tty_chars_in_buffer,  /* chars_in_buffer */
-       read_chan,              /* read */
-       write_chan,             /* write */
-       n_tty_ioctl,            /* ioctl */
-       n_tty_set_termios,      /* set_termios */
-       normal_poll,            /* poll */
-       NULL,                   /* hangup */
-       n_tty_receive_buf,      /* receive_buf */
-       n_tty_write_wakeup      /* write_wakeup */
+       .magic           = TTY_LDISC_MAGIC,
+       .name            = "n_tty",
+       .open            = n_tty_open,
+       .close           = n_tty_close,
+       .flush_buffer    = n_tty_flush_buffer,
+       .chars_in_buffer = n_tty_chars_in_buffer,
+       .read            = read_chan,
+       .write           = write_chan,
+       .ioctl           = n_tty_ioctl,
+       .set_termios     = n_tty_set_termios,
+       .poll            = normal_poll,
+       .receive_buf     = n_tty_receive_buf,
+       .write_wakeup    = n_tty_write_wakeup
 };
 
index fc662e4ce58aebd0f4995c2b880b417549b294fe..fe62c2170d01692fe3e05430aeba5374fc8c1742 100644 (file)
@@ -151,6 +151,12 @@ static int tty_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
              unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+                               unsigned long arg);
+#else
+#define tty_compat_ioctl NULL
+#endif
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_tty(struct tty_struct *tty, int idx);
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
@@ -1143,8 +1149,8 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
        return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
-                            unsigned int cmd, unsigned long arg)
+static long hung_up_tty_ioctl(struct file * file,
+                             unsigned int cmd, unsigned long arg)
 {
        return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
@@ -1155,6 +1161,7 @@ static const struct file_operations tty_fops = {
        .write          = tty_write,
        .poll           = tty_poll,
        .ioctl          = tty_ioctl,
+       .compat_ioctl   = tty_compat_ioctl,
        .open           = tty_open,
        .release        = tty_release,
        .fasync         = tty_fasync,
@@ -1167,6 +1174,7 @@ static const struct file_operations ptmx_fops = {
        .write          = tty_write,
        .poll           = tty_poll,
        .ioctl          = tty_ioctl,
+       .compat_ioctl   = tty_compat_ioctl,
        .open           = ptmx_open,
        .release        = tty_release,
        .fasync         = tty_fasync,
@@ -1179,6 +1187,7 @@ static const struct file_operations console_fops = {
        .write          = redirected_tty_write,
        .poll           = tty_poll,
        .ioctl          = tty_ioctl,
+       .compat_ioctl   = tty_compat_ioctl,
        .open           = tty_open,
        .release        = tty_release,
        .fasync         = tty_fasync,
@@ -1189,7 +1198,8 @@ static const struct file_operations hung_up_tty_fops = {
        .read           = hung_up_tty_read,
        .write          = hung_up_tty_write,
        .poll           = hung_up_tty_poll,
-       .ioctl          = hung_up_tty_ioctl,
+       .unlocked_ioctl = hung_up_tty_ioctl,
+       .compat_ioctl   = hung_up_tty_ioctl,
        .release        = tty_release,
 };
 
@@ -3357,6 +3367,32 @@ int tty_ioctl(struct inode * inode, struct file * file,
        return retval;
 }
 
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct tty_struct *tty = file->private_data;
+       struct tty_ldisc *ld;
+       int retval = -ENOIOCTLCMD;
+
+       if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+               return -EINVAL;
+
+       if (tty->driver->compat_ioctl) {
+               retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
+               if (retval != -ENOIOCTLCMD)
+                       return retval;
+       }
+
+       ld = tty_ldisc_ref_wait(tty);
+       if (ld->compat_ioctl)
+               retval = ld->compat_ioctl(tty, file, cmd, arg);
+       tty_ldisc_deref(ld);
+
+       return retval;
+}
+#endif
 
 /*
  * This implements the "Secure Attention Key" ---  the idea is to
@@ -3689,6 +3725,7 @@ void tty_set_operations(struct tty_driver *driver,
        driver->write_room = op->write_room;
        driver->chars_in_buffer = op->chars_in_buffer;
        driver->ioctl = op->ioctl;
+       driver->compat_ioctl = op->compat_ioctl;
        driver->set_termios = op->set_termios;
        driver->throttle = op->throttle;
        driver->unthrottle = op->unthrottle;
index 659487e3ebeb0c99fcb60526b41cf90a1712877a..85c95cd39bc30faeede4c57fe083d6e943cecfa9 100644 (file)
  *     This routine allows the tty driver to implement
  *     device-specific ioctl's.  If the ioctl number passed in cmd
  *     is not recognized by the driver, it should return ENOIOCTLCMD.
+ *
+ * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ *                     unsigned int cmd, unsigned long arg);
+ *
+ *     implement ioctl processing for 32 bit process on 64 bit system
  * 
  * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
@@ -132,6 +137,8 @@ struct tty_operations {
        int  (*chars_in_buffer)(struct tty_struct *tty);
        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,
+                            unsigned int cmd, unsigned long arg);
        void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        void (*throttle)(struct tty_struct * tty);
        void (*unthrottle)(struct tty_struct * tty);
@@ -193,6 +200,8 @@ struct tty_driver {
        int  (*chars_in_buffer)(struct tty_struct *tty);
        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,
+                            unsigned int cmd, unsigned long arg);
        void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        void (*throttle)(struct tty_struct * tty);
        void (*unthrottle)(struct tty_struct * tty);
index d75932e2771094c7066667a0c6357eb079f480b5..6226504d91080bd10b9eb91e7a6adf4cbc3ab579 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,
+ *                     unsigned int cmd, unsigned long arg);
+ *
+ *      Process ioctl calls from 32-bit process on 64-bit system
+ *
  * void        (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  *     This function notifies the line discpline that a change has
@@ -118,6 +123,8 @@ struct tty_ldisc {
                         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,
+                               unsigned int cmd, unsigned long arg);
        void    (*set_termios)(struct tty_struct *tty, struct ktermios * old);
        unsigned int (*poll)(struct tty_struct *, struct file *,
                             struct poll_table_struct *);