Commit d4eca0f0 authored by Ryan S. Arnold's avatar Ryan S. Arnold Committed by Linus Torvalds

[PATCH] hvc_console fix to prevent oops and late hangup and write operations

This patch prevents execution of hvc_write() and hvc_hangup() after the tty
layer has executed a final hvc_close() against a device.  This patch
provides a better method than was previously used.  tty->driver_data is no
longer invalidated so we'll no longer get oopses when the tty layer allows
late hangup() and write() operations.

- Removed silly tty->driver_data = NULL; from hvc_close which prevents
  possible oops in hvc_write() and hvc_hangup() due to improperly acting
  ldisc close ordering.

- Added hp->count <= 0 check to hvc_write() and hvc_hangup() to prevent
  execution of these function after hvc_close() has been invoked by the tty
  layer.  Same tty ldisc issues as above are the reason.

- Added some comments to clarify the situation.

- Awaiting a forth coming patch from Alan Cox which should clean up the
  close ordering and prevent the late hangup and write ops from happening.
Signed-off-by: default avatarRyan S. Arnold <rsa@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f07dd651
......@@ -221,6 +221,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
spin_unlock_irqrestore(&hp->lock, flags);
tty->driver_data = NULL;
kobject_put(kobjp);
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
}
/* Force wakeup of the polling thread */
hvc_kick();
......@@ -240,7 +241,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
/*
* No driver_data means that this close was issued after a failed
* hvcs_open by the tty layer's release_dev() function and we can just
* hvc_open by the tty layer's release_dev() function and we can just
* exit cleanly because the kobject reference wasn't made.
*/
if (!tty->driver_data)
......@@ -266,13 +267,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
*/
tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
/*
* Since the line disc doesn't block writes during tty close
* operations we'll set driver_data to NULL and then make sure
* to check tty->driver_data for NULL in hvc_write().
*/
tty->driver_data = NULL;
if (irq != NO_IRQ)
free_irq(irq, hp);
......@@ -294,7 +288,21 @@ static void hvc_hangup(struct tty_struct *tty)
int temp_open_count;
struct kobject *kobjp;
if (!hp)
return;
spin_lock_irqsave(&hp->lock, flags);
/*
* The N_TTY line discipline has problems such that in a close vs
* open->hangup case this can be called after the final close so prevent
* that from happening for now.
*/
if (hp->count <= 0) {
spin_unlock_irqrestore(&hp->lock, flags);
return;
}
kobjp = &hp->kobj;
temp_open_count = hp->count;
hp->count = 0;
......@@ -428,6 +436,9 @@ static int hvc_write(struct tty_struct *tty, int from_user,
if (!hp)
return -EPIPE;
if (hp->count <= 0)
return -EIO;
if (from_user)
written = __hvc_write_user(hp, buf, count);
else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment