Skip to content

Commit

Permalink
tty: add compat_ioctl
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Fulghum authored and Linus Torvalds committed May 11, 2007
1 parent 108f39a commit e10cc1d
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 19 deletions.
29 changes: 13 additions & 16 deletions drivers/char/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

43 changes: 40 additions & 3 deletions drivers/char/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
};

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions include/linux/tty_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
* 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);
*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions include/linux/tty_ldisc.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
* 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
Expand Down Expand Up @@ -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 *);
Expand Down

0 comments on commit e10cc1d

Please sign in to comment.