|
@@ -1556,6 +1556,62 @@ static void release_tty(struct tty_struct *tty, int idx)
|
|
|
tty_kref_put(tty);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * tty_release_checks - check a tty before real release
|
|
|
+ * @tty: tty to check
|
|
|
+ * @o_tty: link of @tty (if any)
|
|
|
+ * @idx: index of the tty
|
|
|
+ *
|
|
|
+ * Performs some paranoid checking before true release of the @tty.
|
|
|
+ * This is a no-op unless TTY_PARANOIA_CHECK is defined.
|
|
|
+ */
|
|
|
+static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty,
|
|
|
+ int idx)
|
|
|
+{
|
|
|
+#ifdef TTY_PARANOIA_CHECK
|
|
|
+ if (idx < 0 || idx >= tty->driver->num) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
|
|
|
+ "free (%s)\n", tty->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* not much to check for devpts */
|
|
|
+ if (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (tty != tty->driver->ttys[idx]) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
|
|
|
+ "for (%s)\n", idx, tty->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (tty->termios != tty->driver->termios[idx]) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
|
|
|
+ "for (%s)\n",
|
|
|
+ idx, tty->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (tty->driver->other) {
|
|
|
+ if (o_tty != tty->driver->other->ttys[idx]) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
|
|
|
+ "not o_tty for (%s)\n",
|
|
|
+ idx, tty->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (o_tty->termios != tty->driver->other->termios[idx]) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
|
|
|
+ "not o_termios for (%s)\n",
|
|
|
+ idx, tty->name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (o_tty->link != tty) {
|
|
|
+ printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* tty_release - vfs callback for close
|
|
|
* @inode: inode of tty
|
|
@@ -1598,59 +1654,16 @@ int tty_release(struct inode *inode, struct file *filp)
|
|
|
devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
|
|
|
o_tty = tty->link;
|
|
|
|
|
|
-#ifdef TTY_PARANOIA_CHECK
|
|
|
- if (idx < 0 || idx >= tty->driver->num) {
|
|
|
- printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
|
|
|
- "free (%s)\n", tty->name);
|
|
|
+ if (tty_release_checks(tty, o_tty, idx)) {
|
|
|
tty_unlock();
|
|
|
return 0;
|
|
|
}
|
|
|
- if (!devpts) {
|
|
|
- if (tty != tty->driver->ttys[idx]) {
|
|
|
- tty_unlock();
|
|
|
- printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
|
|
|
- "for (%s)\n", idx, tty->name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (tty->termios != tty->driver->termios[idx]) {
|
|
|
- tty_unlock();
|
|
|
- printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
|
|
|
- "for (%s)\n",
|
|
|
- idx, tty->name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
|
|
|
#ifdef TTY_DEBUG_HANGUP
|
|
|
printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...",
|
|
|
tty_name(tty, buf), tty->count);
|
|
|
#endif
|
|
|
|
|
|
-#ifdef TTY_PARANOIA_CHECK
|
|
|
- if (tty->driver->other &&
|
|
|
- !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
|
|
|
- if (o_tty != tty->driver->other->ttys[idx]) {
|
|
|
- tty_unlock();
|
|
|
- printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
|
|
|
- "not o_tty for (%s)\n",
|
|
|
- idx, tty->name);
|
|
|
- return 0 ;
|
|
|
- }
|
|
|
- if (o_tty->termios != tty->driver->other->termios[idx]) {
|
|
|
- tty_unlock();
|
|
|
- printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
|
|
|
- "not o_termios for (%s)\n",
|
|
|
- idx, tty->name);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (o_tty->link != tty) {
|
|
|
- tty_unlock();
|
|
|
- printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif
|
|
|
if (tty->ops->close)
|
|
|
tty->ops->close(tty, filp);
|
|
|
|