diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:39:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:41 -0400 |
commit | 452a00d2ee288f2cbc36f676edd06cb14d2878c1 (patch) | |
tree | c8251c73924a6ac9b174bc557357bfeff0c8d1a8 | |
parent | f4d2a6c2096b764decb20070b1bf4356de9144a8 (diff) |
tty: Make get_current_tty use a kref
We now return a kref covered tty reference. That ensures the tty structure
doesn't go away when you have a return from get_current_tty. This is not
enough to protect you from most of the resources being freed behind your
back - yet.
[Updated to include fixes for SELinux problems found by Andrew Morton and
an s390 leak found while debugging the former]
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/char/tty_io.c | 10 | ||||
-rw-r--r-- | drivers/s390/char/fs3270.c | 3 | ||||
-rw-r--r-- | fs/dquot.c | 6 | ||||
-rw-r--r-- | security/selinux/hooks.c | 3 |
4 files changed, 13 insertions, 9 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 9a76db3cda1c..4c0e4ed31a48 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -786,12 +786,12 @@ void disassociate_ctty(int on_exit) | |||
786 | tty = get_current_tty(); | 786 | tty = get_current_tty(); |
787 | if (tty) { | 787 | if (tty) { |
788 | tty_pgrp = get_pid(tty->pgrp); | 788 | tty_pgrp = get_pid(tty->pgrp); |
789 | lock_kernel(); | ||
790 | mutex_unlock(&tty_mutex); | 789 | mutex_unlock(&tty_mutex); |
791 | /* XXX: here we race, there is nothing protecting tty */ | 790 | lock_kernel(); |
792 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 791 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
793 | tty_vhangup(tty); | 792 | tty_vhangup(tty); |
794 | unlock_kernel(); | 793 | unlock_kernel(); |
794 | tty_kref_put(tty); | ||
795 | } else if (on_exit) { | 795 | } else if (on_exit) { |
796 | struct pid *old_pgrp; | 796 | struct pid *old_pgrp; |
797 | spin_lock_irq(¤t->sighand->siglock); | 797 | spin_lock_irq(¤t->sighand->siglock); |
@@ -819,7 +819,6 @@ void disassociate_ctty(int on_exit) | |||
819 | spin_unlock_irq(¤t->sighand->siglock); | 819 | spin_unlock_irq(¤t->sighand->siglock); |
820 | 820 | ||
821 | mutex_lock(&tty_mutex); | 821 | mutex_lock(&tty_mutex); |
822 | /* It is possible that do_tty_hangup has free'd this tty */ | ||
823 | tty = get_current_tty(); | 822 | tty = get_current_tty(); |
824 | if (tty) { | 823 | if (tty) { |
825 | unsigned long flags; | 824 | unsigned long flags; |
@@ -829,6 +828,7 @@ void disassociate_ctty(int on_exit) | |||
829 | tty->session = NULL; | 828 | tty->session = NULL; |
830 | tty->pgrp = NULL; | 829 | tty->pgrp = NULL; |
831 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 830 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
831 | tty_kref_put(tty); | ||
832 | } else { | 832 | } else { |
833 | #ifdef TTY_DEBUG_HANGUP | 833 | #ifdef TTY_DEBUG_HANGUP |
834 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" | 834 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" |
@@ -1806,6 +1806,8 @@ retry_open: | |||
1806 | index = tty->index; | 1806 | index = tty->index; |
1807 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | 1807 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
1808 | /* noctty = 1; */ | 1808 | /* noctty = 1; */ |
1809 | /* FIXME: Should we take a driver reference ? */ | ||
1810 | tty_kref_put(tty); | ||
1809 | goto got_driver; | 1811 | goto got_driver; |
1810 | } | 1812 | } |
1811 | #ifdef CONFIG_VT | 1813 | #ifdef CONFIG_VT |
@@ -3135,7 +3137,7 @@ struct tty_struct *get_current_tty(void) | |||
3135 | { | 3137 | { |
3136 | struct tty_struct *tty; | 3138 | struct tty_struct *tty; |
3137 | WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); | 3139 | WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); |
3138 | tty = current->signal->tty; | 3140 | tty = tty_kref_get(current->signal->tty); |
3139 | /* | 3141 | /* |
3140 | * session->tty can be changed/cleared from under us, make sure we | 3142 | * session->tty can be changed/cleared from under us, make sure we |
3141 | * issue the load. The obtained pointer, when not NULL, is valid as | 3143 | * issue the load. The obtained pointer, when not NULL, is valid as |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index d18e6d2e0b49..3ef5425d0eb8 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -430,11 +430,12 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
430 | mutex_lock(&tty_mutex); | 430 | mutex_lock(&tty_mutex); |
431 | tty = get_current_tty(); | 431 | tty = get_current_tty(); |
432 | if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { | 432 | if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { |
433 | mutex_unlock(&tty_mutex); | 433 | tty_kref_put(tty); |
434 | rc = -ENODEV; | 434 | rc = -ENODEV; |
435 | goto out; | 435 | goto out; |
436 | } | 436 | } |
437 | minor = tty->index + RAW3270_FIRSTMINOR; | 437 | minor = tty->index + RAW3270_FIRSTMINOR; |
438 | tty_kref_put(tty); | ||
438 | mutex_unlock(&tty_mutex); | 439 | mutex_unlock(&tty_mutex); |
439 | } | 440 | } |
440 | /* Check if some other program is already using fullscreen mode. */ | 441 | /* Check if some other program is already using fullscreen mode. */ |
diff --git a/fs/dquot.c b/fs/dquot.c index 8ec4d6cc7633..7417a6ca3129 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -897,8 +897,9 @@ static void print_warning(struct dquot *dquot, const int warntype) | |||
897 | 897 | ||
898 | mutex_lock(&tty_mutex); | 898 | mutex_lock(&tty_mutex); |
899 | tty = get_current_tty(); | 899 | tty = get_current_tty(); |
900 | mutex_unlock(&tty_mutex); | ||
900 | if (!tty) | 901 | if (!tty) |
901 | goto out_lock; | 902 | return; |
902 | tty_write_message(tty, dquot->dq_sb->s_id); | 903 | tty_write_message(tty, dquot->dq_sb->s_id); |
903 | if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN) | 904 | if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN) |
904 | tty_write_message(tty, ": warning, "); | 905 | tty_write_message(tty, ": warning, "); |
@@ -926,8 +927,7 @@ static void print_warning(struct dquot *dquot, const int warntype) | |||
926 | break; | 927 | break; |
927 | } | 928 | } |
928 | tty_write_message(tty, msg); | 929 | tty_write_message(tty, msg); |
929 | out_lock: | 930 | tty_kref_put(tty); |
930 | mutex_unlock(&tty_mutex); | ||
931 | } | 931 | } |
932 | #endif | 932 | #endif |
933 | 933 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4a7374c12d9c..089d61a23952 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2123,6 +2123,7 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2123 | 2123 | ||
2124 | mutex_lock(&tty_mutex); | 2124 | mutex_lock(&tty_mutex); |
2125 | tty = get_current_tty(); | 2125 | tty = get_current_tty(); |
2126 | mutex_unlock(&tty_mutex); | ||
2126 | if (tty) { | 2127 | if (tty) { |
2127 | file_list_lock(); | 2128 | file_list_lock(); |
2128 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); | 2129 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); |
@@ -2139,8 +2140,8 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2139 | } | 2140 | } |
2140 | } | 2141 | } |
2141 | file_list_unlock(); | 2142 | file_list_unlock(); |
2143 | tty_kref_put(tty); | ||
2142 | } | 2144 | } |
2143 | mutex_unlock(&tty_mutex); | ||
2144 | /* Reset controlling tty. */ | 2145 | /* Reset controlling tty. */ |
2145 | if (drop_tty) | 2146 | if (drop_tty) |
2146 | no_tty(); | 2147 | no_tty(); |