diff options
Diffstat (limited to 'drivers/char/tty_io.c')
| -rw-r--r-- | drivers/char/tty_io.c | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index cd5b829634ea..949067a0bd47 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -188,6 +188,41 @@ void free_tty_struct(struct tty_struct *tty) | |||
| 188 | kfree(tty); | 188 | kfree(tty); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static inline struct tty_struct *file_tty(struct file *file) | ||
| 192 | { | ||
| 193 | return ((struct tty_file_private *)file->private_data)->tty; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Associate a new file with the tty structure */ | ||
| 197 | void tty_add_file(struct tty_struct *tty, struct file *file) | ||
| 198 | { | ||
| 199 | struct tty_file_private *priv; | ||
| 200 | |||
| 201 | /* XXX: must implement proper error handling in callers */ | ||
| 202 | priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL); | ||
| 203 | |||
| 204 | priv->tty = tty; | ||
| 205 | priv->file = file; | ||
| 206 | file->private_data = priv; | ||
| 207 | |||
| 208 | spin_lock(&tty_files_lock); | ||
| 209 | list_add(&priv->list, &tty->tty_files); | ||
| 210 | spin_unlock(&tty_files_lock); | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Delete file from its tty */ | ||
| 214 | void tty_del_file(struct file *file) | ||
| 215 | { | ||
| 216 | struct tty_file_private *priv = file->private_data; | ||
| 217 | |||
| 218 | spin_lock(&tty_files_lock); | ||
| 219 | list_del(&priv->list); | ||
| 220 | spin_unlock(&tty_files_lock); | ||
| 221 | file->private_data = NULL; | ||
| 222 | kfree(priv); | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 191 | #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) | 226 | #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) |
| 192 | 227 | ||
| 193 | /** | 228 | /** |
| @@ -500,6 +535,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
| 500 | struct file *cons_filp = NULL; | 535 | struct file *cons_filp = NULL; |
| 501 | struct file *filp, *f = NULL; | 536 | struct file *filp, *f = NULL; |
| 502 | struct task_struct *p; | 537 | struct task_struct *p; |
| 538 | struct tty_file_private *priv; | ||
| 503 | int closecount = 0, n; | 539 | int closecount = 0, n; |
| 504 | unsigned long flags; | 540 | unsigned long flags; |
| 505 | int refs = 0; | 541 | int refs = 0; |
| @@ -509,7 +545,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
| 509 | 545 | ||
| 510 | 546 | ||
| 511 | spin_lock(&redirect_lock); | 547 | spin_lock(&redirect_lock); |
| 512 | if (redirect && redirect->private_data == tty) { | 548 | if (redirect && file_tty(redirect) == tty) { |
| 513 | f = redirect; | 549 | f = redirect; |
| 514 | redirect = NULL; | 550 | redirect = NULL; |
| 515 | } | 551 | } |
| @@ -524,7 +560,8 @@ void __tty_hangup(struct tty_struct *tty) | |||
| 524 | 560 | ||
| 525 | spin_lock(&tty_files_lock); | 561 | spin_lock(&tty_files_lock); |
| 526 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 562 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
| 527 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 563 | list_for_each_entry(priv, &tty->tty_files, list) { |
| 564 | filp = priv->file; | ||
| 528 | if (filp->f_op->write == redirected_tty_write) | 565 | if (filp->f_op->write == redirected_tty_write) |
| 529 | cons_filp = filp; | 566 | cons_filp = filp; |
| 530 | if (filp->f_op->write != tty_write) | 567 | if (filp->f_op->write != tty_write) |
| @@ -892,12 +929,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
| 892 | loff_t *ppos) | 929 | loff_t *ppos) |
| 893 | { | 930 | { |
| 894 | int i; | 931 | int i; |
| 895 | struct tty_struct *tty; | 932 | struct inode *inode = file->f_path.dentry->d_inode; |
| 896 | struct inode *inode; | 933 | struct tty_struct *tty = file_tty(file); |
| 897 | struct tty_ldisc *ld; | 934 | struct tty_ldisc *ld; |
| 898 | 935 | ||
| 899 | tty = file->private_data; | ||
| 900 | inode = file->f_path.dentry->d_inode; | ||
| 901 | if (tty_paranoia_check(tty, inode, "tty_read")) | 936 | if (tty_paranoia_check(tty, inode, "tty_read")) |
| 902 | return -EIO; | 937 | return -EIO; |
| 903 | if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) | 938 | if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) |
| @@ -1068,12 +1103,11 @@ void tty_write_message(struct tty_struct *tty, char *msg) | |||
| 1068 | static ssize_t tty_write(struct file *file, const char __user *buf, | 1103 | static ssize_t tty_write(struct file *file, const char __user *buf, |
| 1069 | size_t count, loff_t *ppos) | 1104 | size_t count, loff_t *ppos) |
| 1070 | { | 1105 | { |
| 1071 | struct tty_struct *tty; | ||
| 1072 | struct inode *inode = file->f_path.dentry->d_inode; | 1106 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1107 | struct tty_struct *tty = file_tty(file); | ||
| 1108 | struct tty_ldisc *ld; | ||
| 1073 | ssize_t ret; | 1109 | ssize_t ret; |
| 1074 | struct tty_ldisc *ld; | ||
| 1075 | 1110 | ||
| 1076 | tty = file->private_data; | ||
| 1077 | if (tty_paranoia_check(tty, inode, "tty_write")) | 1111 | if (tty_paranoia_check(tty, inode, "tty_write")) |
| 1078 | return -EIO; | 1112 | return -EIO; |
| 1079 | if (!tty || !tty->ops->write || | 1113 | if (!tty || !tty->ops->write || |
| @@ -1510,13 +1544,13 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
| 1510 | 1544 | ||
| 1511 | int tty_release(struct inode *inode, struct file *filp) | 1545 | int tty_release(struct inode *inode, struct file *filp) |
| 1512 | { | 1546 | { |
| 1513 | struct tty_struct *tty, *o_tty; | 1547 | struct tty_struct *tty = file_tty(filp); |
| 1548 | struct tty_struct *o_tty; | ||
| 1514 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1549 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
| 1515 | int devpts; | 1550 | int devpts; |
| 1516 | int idx; | 1551 | int idx; |
| 1517 | char buf[64]; | 1552 | char buf[64]; |
| 1518 | 1553 | ||
| 1519 | tty = filp->private_data; | ||
| 1520 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1554 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
| 1521 | return 0; | 1555 | return 0; |
| 1522 | 1556 | ||
| @@ -1674,11 +1708,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
| 1674 | * - do_tty_hangup no longer sees this file descriptor as | 1708 | * - do_tty_hangup no longer sees this file descriptor as |
| 1675 | * something that needs to be handled for hangups. | 1709 | * something that needs to be handled for hangups. |
| 1676 | */ | 1710 | */ |
| 1677 | spin_lock(&tty_files_lock); | 1711 | tty_del_file(filp); |
| 1678 | BUG_ON(list_empty(&filp->f_u.fu_list)); | ||
| 1679 | list_del_init(&filp->f_u.fu_list); | ||
| 1680 | spin_unlock(&tty_files_lock); | ||
| 1681 | filp->private_data = NULL; | ||
| 1682 | 1712 | ||
| 1683 | /* | 1713 | /* |
| 1684 | * Perform some housekeeping before deciding whether to return. | 1714 | * Perform some housekeeping before deciding whether to return. |
| @@ -1845,12 +1875,8 @@ got_driver: | |||
| 1845 | return PTR_ERR(tty); | 1875 | return PTR_ERR(tty); |
| 1846 | } | 1876 | } |
| 1847 | 1877 | ||
| 1848 | filp->private_data = tty; | 1878 | tty_add_file(tty, filp); |
| 1849 | BUG_ON(list_empty(&filp->f_u.fu_list)); | 1879 | |
| 1850 | file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ | ||
| 1851 | spin_lock(&tty_files_lock); | ||
| 1852 | list_add(&filp->f_u.fu_list, &tty->tty_files); | ||
| 1853 | spin_unlock(&tty_files_lock); | ||
| 1854 | check_tty_count(tty, "tty_open"); | 1880 | check_tty_count(tty, "tty_open"); |
| 1855 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1881 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
| 1856 | tty->driver->subtype == PTY_TYPE_MASTER) | 1882 | tty->driver->subtype == PTY_TYPE_MASTER) |
| @@ -1926,11 +1952,10 @@ got_driver: | |||
| 1926 | 1952 | ||
| 1927 | static unsigned int tty_poll(struct file *filp, poll_table *wait) | 1953 | static unsigned int tty_poll(struct file *filp, poll_table *wait) |
| 1928 | { | 1954 | { |
| 1929 | struct tty_struct *tty; | 1955 | struct tty_struct *tty = file_tty(filp); |
| 1930 | struct tty_ldisc *ld; | 1956 | struct tty_ldisc *ld; |
| 1931 | int ret = 0; | 1957 | int ret = 0; |
| 1932 | 1958 | ||
| 1933 | tty = filp->private_data; | ||
| 1934 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) | 1959 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) |
| 1935 | return 0; | 1960 | return 0; |
| 1936 | 1961 | ||
| @@ -1943,11 +1968,10 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
| 1943 | 1968 | ||
| 1944 | static int __tty_fasync(int fd, struct file *filp, int on) | 1969 | static int __tty_fasync(int fd, struct file *filp, int on) |
| 1945 | { | 1970 | { |
| 1946 | struct tty_struct *tty; | 1971 | struct tty_struct *tty = file_tty(filp); |
| 1947 | unsigned long flags; | 1972 | unsigned long flags; |
| 1948 | int retval = 0; | 1973 | int retval = 0; |
| 1949 | 1974 | ||
| 1950 | tty = filp->private_data; | ||
| 1951 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) | 1975 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) |
| 1952 | goto out; | 1976 | goto out; |
| 1953 | 1977 | ||
| @@ -2501,13 +2525,13 @@ EXPORT_SYMBOL(tty_pair_get_pty); | |||
| 2501 | */ | 2525 | */ |
| 2502 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2526 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 2503 | { | 2527 | { |
| 2504 | struct tty_struct *tty, *real_tty; | 2528 | struct tty_struct *tty = file_tty(file); |
| 2529 | struct tty_struct *real_tty; | ||
| 2505 | void __user *p = (void __user *)arg; | 2530 | void __user *p = (void __user *)arg; |
| 2506 | int retval; | 2531 | int retval; |
| 2507 | struct tty_ldisc *ld; | 2532 | struct tty_ldisc *ld; |
| 2508 | struct inode *inode = file->f_dentry->d_inode; | 2533 | struct inode *inode = file->f_dentry->d_inode; |
| 2509 | 2534 | ||
| 2510 | tty = file->private_data; | ||
| 2511 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2535 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
| 2512 | return -EINVAL; | 2536 | return -EINVAL; |
| 2513 | 2537 | ||
| @@ -2629,7 +2653,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 2629 | unsigned long arg) | 2653 | unsigned long arg) |
| 2630 | { | 2654 | { |
| 2631 | struct inode *inode = file->f_dentry->d_inode; | 2655 | struct inode *inode = file->f_dentry->d_inode; |
| 2632 | struct tty_struct *tty = file->private_data; | 2656 | struct tty_struct *tty = file_tty(file); |
| 2633 | struct tty_ldisc *ld; | 2657 | struct tty_ldisc *ld; |
| 2634 | int retval = -ENOIOCTLCMD; | 2658 | int retval = -ENOIOCTLCMD; |
| 2635 | 2659 | ||
| @@ -2721,7 +2745,7 @@ void __do_SAK(struct tty_struct *tty) | |||
| 2721 | if (!filp) | 2745 | if (!filp) |
| 2722 | continue; | 2746 | continue; |
| 2723 | if (filp->f_op->read == tty_read && | 2747 | if (filp->f_op->read == tty_read && |
| 2724 | filp->private_data == tty) { | 2748 | file_tty(filp) == tty) { |
| 2725 | printk(KERN_NOTICE "SAK: killed process %d" | 2749 | printk(KERN_NOTICE "SAK: killed process %d" |
| 2726 | " (%s): fd#%d opened to the tty\n", | 2750 | " (%s): fd#%d opened to the tty\n", |
| 2727 | task_pid_nr(p), p->comm, i); | 2751 | task_pid_nr(p), p->comm, i); |
