aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-09-29 05:00:58 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-29 12:18:18 -0400
commit28298232a15c48ea9835d5d24577cde87923e55c (patch)
tree09075921f79015bdb83dfd571a891d3a111c3796
parentde2a84f2be8ed8a166f13d6aa2ae474541172bb2 (diff)
[PATCH] tty: Fix bits and note more bits to fix
If your driver implements "break on" and "break off" this ensures you won't get multiple overlapping requests or requests in parallel. If your driver has its own break handling then its still your problem as the driver author. Break is also now serialized against writes from user space properly but no new guarantees are made driver level about writes from the line discipline itself (eg flow control or echo) Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/tty_io.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 48b59006afcd..635437319778 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2719,6 +2719,8 @@ static int tty_fasync(int fd, struct file * filp, int on)
2719 * Locking: 2719 * Locking:
2720 * Called functions take tty_ldisc_lock 2720 * Called functions take tty_ldisc_lock
2721 * current->signal->tty check is safe without locks 2721 * current->signal->tty check is safe without locks
2722 *
2723 * FIXME: may race normal receive processing
2722 */ 2724 */
2723 2725
2724static int tiocsti(struct tty_struct *tty, char __user *p) 2726static int tiocsti(struct tty_struct *tty, char __user *p)
@@ -2878,9 +2880,7 @@ static int fionbio(struct file *file, int __user *p)
2878 * Locking: 2880 * Locking:
2879 * Takes tasklist lock internally to walk sessions 2881 * Takes tasklist lock internally to walk sessions
2880 * Takes task_lock() when updating signal->tty 2882 * Takes task_lock() when updating signal->tty
2881 * 2883 * Takes tty_mutex() to protect tty instance
2882 * FIXME: tty_mutex is needed to protect signal->tty references.
2883 * FIXME: why task_lock on the signal->tty reference ??
2884 * 2884 *
2885 */ 2885 */
2886 2886
@@ -2915,9 +2915,11 @@ static int tiocsctty(struct tty_struct *tty, int arg)
2915 } else 2915 } else
2916 return -EPERM; 2916 return -EPERM;
2917 } 2917 }
2918 mutex_lock(&tty_mutex);
2918 task_lock(current); 2919 task_lock(current);
2919 current->signal->tty = tty; 2920 current->signal->tty = tty;
2920 task_unlock(current); 2921 task_unlock(current);
2922 mutex_unlock(&tty_mutex);
2921 current->signal->tty_old_pgrp = 0; 2923 current->signal->tty_old_pgrp = 0;
2922 tty->session = current->signal->session; 2924 tty->session = current->signal->session;
2923 tty->pgrp = process_group(current); 2925 tty->pgrp = process_group(current);
@@ -2957,8 +2959,6 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
2957 * permitted where the tty session is our session. 2959 * permitted where the tty session is our session.
2958 * 2960 *
2959 * Locking: None 2961 * Locking: None
2960 *
2961 * FIXME: current->signal->tty referencing is unsafe.
2962 */ 2962 */
2963 2963
2964static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) 2964static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3037,19 +3037,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
3037 * timed break functionality. 3037 * timed break functionality.
3038 * 3038 *
3039 * Locking: 3039 * Locking:
3040 * None 3040 * atomic_write_lock serializes
3041 * 3041 *
3042 * FIXME:
3043 * What if two overlap
3044 */ 3042 */
3045 3043
3046static int send_break(struct tty_struct *tty, unsigned int duration) 3044static int send_break(struct tty_struct *tty, unsigned int duration)
3047{ 3045{
3046 if (mutex_lock_interruptible(&tty->atomic_write_lock))
3047 return -EINTR;
3048 tty->driver->break_ctl(tty, -1); 3048 tty->driver->break_ctl(tty, -1);
3049 if (!signal_pending(current)) { 3049 if (!signal_pending(current)) {
3050 msleep_interruptible(duration); 3050 msleep_interruptible(duration);
3051 } 3051 }
3052 tty->driver->break_ctl(tty, 0); 3052 tty->driver->break_ctl(tty, 0);
3053 mutex_unlock(&tty->atomic_write_lock);
3053 if (signal_pending(current)) 3054 if (signal_pending(current))
3054 return -EINTR; 3055 return -EINTR;
3055 return 0; 3056 return 0;
@@ -3142,6 +3143,8 @@ int tty_ioctl(struct inode * inode, struct file * file,
3142 if (tty_paranoia_check(tty, inode, "tty_ioctl")) 3143 if (tty_paranoia_check(tty, inode, "tty_ioctl"))
3143 return -EINVAL; 3144 return -EINVAL;
3144 3145
3146 /* CHECKME: is this safe as one end closes ? */
3147
3145 real_tty = tty; 3148 real_tty = tty;
3146 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 3149 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
3147 tty->driver->subtype == PTY_TYPE_MASTER) 3150 tty->driver->subtype == PTY_TYPE_MASTER)