diff options
-rw-r--r-- | drivers/char/pty.c | 6 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 84 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | include/linux/tty.h | 8 | ||||
-rw-r--r-- | security/selinux/hooks.c | 5 |
6 files changed, 69 insertions, 38 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 2c64faa8efa4..c350d01716bd 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -675,12 +675,8 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
675 | } | 675 | } |
676 | 676 | ||
677 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 677 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
678 | filp->private_data = tty; | ||
679 | 678 | ||
680 | file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ | 679 | tty_add_file(tty, filp); |
681 | spin_lock(&tty_files_lock); | ||
682 | list_add(&filp->f_u.fu_list, &tty->tty_files); | ||
683 | spin_unlock(&tty_files_lock); | ||
684 | 680 | ||
685 | retval = devpts_pty_new(inode, tty->link); | 681 | retval = devpts_pty_new(inode, tty->link); |
686 | if (retval) | 682 | if (retval) |
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); |
diff --git a/fs/internal.h b/fs/internal.h index 6b706bc60a66..6a5c13a80660 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -80,6 +80,8 @@ extern void chroot_fs_refs(struct path *, struct path *); | |||
80 | /* | 80 | /* |
81 | * file_table.c | 81 | * file_table.c |
82 | */ | 82 | */ |
83 | extern void file_sb_list_add(struct file *f, struct super_block *sb); | ||
84 | extern void file_sb_list_del(struct file *f); | ||
83 | extern void mark_files_ro(struct super_block *); | 85 | extern void mark_files_ro(struct super_block *); |
84 | extern struct file *get_empty_filp(void); | 86 | extern struct file *get_empty_filp(void); |
85 | 87 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 5a9a9e5a3705..5e65add0f163 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2185,8 +2185,6 @@ static inline void insert_inode_hash(struct inode *inode) { | |||
2185 | __insert_inode_hash(inode, inode->i_ino); | 2185 | __insert_inode_hash(inode, inode->i_ino); |
2186 | } | 2186 | } |
2187 | 2187 | ||
2188 | extern void file_sb_list_add(struct file *f, struct super_block *sb); | ||
2189 | extern void file_sb_list_del(struct file *f); | ||
2190 | #ifdef CONFIG_BLOCK | 2188 | #ifdef CONFIG_BLOCK |
2191 | extern void submit_bio(int, struct bio *); | 2189 | extern void submit_bio(int, struct bio *); |
2192 | extern int bdev_read_only(struct block_device *); | 2190 | extern int bdev_read_only(struct block_device *); |
diff --git a/include/linux/tty.h b/include/linux/tty.h index f6b371a2514e..67d64e6efe7a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -329,6 +329,13 @@ struct tty_struct { | |||
329 | struct tty_port *port; | 329 | struct tty_port *port; |
330 | }; | 330 | }; |
331 | 331 | ||
332 | /* Each of a tty's open files has private_data pointing to tty_file_private */ | ||
333 | struct tty_file_private { | ||
334 | struct tty_struct *tty; | ||
335 | struct file *file; | ||
336 | struct list_head list; | ||
337 | }; | ||
338 | |||
332 | /* tty magic number */ | 339 | /* tty magic number */ |
333 | #define TTY_MAGIC 0x5401 | 340 | #define TTY_MAGIC 0x5401 |
334 | 341 | ||
@@ -458,6 +465,7 @@ extern void proc_clear_tty(struct task_struct *p); | |||
458 | extern struct tty_struct *get_current_tty(void); | 465 | extern struct tty_struct *get_current_tty(void); |
459 | extern void tty_default_fops(struct file_operations *fops); | 466 | extern void tty_default_fops(struct file_operations *fops); |
460 | extern struct tty_struct *alloc_tty_struct(void); | 467 | extern struct tty_struct *alloc_tty_struct(void); |
468 | extern void tty_add_file(struct tty_struct *tty, struct file *file); | ||
461 | extern void free_tty_struct(struct tty_struct *tty); | 469 | extern void free_tty_struct(struct tty_struct *tty); |
462 | extern void initialize_tty_struct(struct tty_struct *tty, | 470 | extern void initialize_tty_struct(struct tty_struct *tty, |
463 | struct tty_driver *driver, int idx); | 471 | struct tty_driver *driver, int idx); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bd7da0f0ccf3..4796ddd4e721 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2172,6 +2172,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2172 | if (tty) { | 2172 | if (tty) { |
2173 | spin_lock(&tty_files_lock); | 2173 | spin_lock(&tty_files_lock); |
2174 | if (!list_empty(&tty->tty_files)) { | 2174 | if (!list_empty(&tty->tty_files)) { |
2175 | struct tty_file_private *file_priv; | ||
2175 | struct inode *inode; | 2176 | struct inode *inode; |
2176 | 2177 | ||
2177 | /* Revalidate access to controlling tty. | 2178 | /* Revalidate access to controlling tty. |
@@ -2179,7 +2180,9 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2179 | than using file_has_perm, as this particular open | 2180 | than using file_has_perm, as this particular open |
2180 | file may belong to another process and we are only | 2181 | file may belong to another process and we are only |
2181 | interested in the inode-based check here. */ | 2182 | interested in the inode-based check here. */ |
2182 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); | 2183 | file_priv = list_first_entry(&tty->tty_files, |
2184 | struct tty_file_private, list); | ||
2185 | file = file_priv->file; | ||
2183 | inode = file->f_path.dentry->d_inode; | 2186 | inode = file->f_path.dentry->d_inode; |
2184 | if (inode_has_perm(cred, inode, | 2187 | if (inode_has_perm(cred, inode, |
2185 | FILE__READ | FILE__WRITE, NULL)) { | 2188 | FILE__READ | FILE__WRITE, NULL)) { |