diff options
author | Jiri Slaby <jslaby@suse.cz> | 2011-11-11 04:47:23 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-15 18:52:47 -0500 |
commit | 955787ca94a17bdfd00e369a21ceb97aa21792fc (patch) | |
tree | 16bd8e8a7c154be15dcb0c7375c4c8c2c7c019c9 /drivers/tty/tty_io.c | |
parent | 2cd0050cf3ec4da847c3a2f7d95cffd548aef39d (diff) |
TTY: move debug checking out of tty_release
There is no need to taint the tty_release code with paranoia
checking. So move it out of line to a separate function. Making thus
tty_release more readable.
[v2] don't introduce a hard to reproduce use after free (scheduled work would
need to preempt the current thread)
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 101 |
1 files changed, 57 insertions, 44 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 76e66ff5e65d..b874b6d1b0be 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -1557,6 +1557,62 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1557 | } | 1557 | } |
1558 | 1558 | ||
1559 | /** | 1559 | /** |
1560 | * tty_release_checks - check a tty before real release | ||
1561 | * @tty: tty to check | ||
1562 | * @o_tty: link of @tty (if any) | ||
1563 | * @idx: index of the tty | ||
1564 | * | ||
1565 | * Performs some paranoid checking before true release of the @tty. | ||
1566 | * This is a no-op unless TTY_PARANOIA_CHECK is defined. | ||
1567 | */ | ||
1568 | static int tty_release_checks(struct tty_struct *tty, struct tty_struct *o_tty, | ||
1569 | int idx) | ||
1570 | { | ||
1571 | #ifdef TTY_PARANOIA_CHECK | ||
1572 | if (idx < 0 || idx >= tty->driver->num) { | ||
1573 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | ||
1574 | "free (%s)\n", tty->name); | ||
1575 | return -1; | ||
1576 | } | ||
1577 | |||
1578 | /* not much to check for devpts */ | ||
1579 | if (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) | ||
1580 | return 0; | ||
1581 | |||
1582 | if (tty != tty->driver->ttys[idx]) { | ||
1583 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | ||
1584 | "for (%s)\n", idx, tty->name); | ||
1585 | return -1; | ||
1586 | } | ||
1587 | if (tty->termios != tty->driver->termios[idx]) { | ||
1588 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | ||
1589 | "for (%s)\n", | ||
1590 | idx, tty->name); | ||
1591 | return -1; | ||
1592 | } | ||
1593 | if (tty->driver->other) { | ||
1594 | if (o_tty != tty->driver->other->ttys[idx]) { | ||
1595 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | ||
1596 | "not o_tty for (%s)\n", | ||
1597 | idx, tty->name); | ||
1598 | return -1; | ||
1599 | } | ||
1600 | if (o_tty->termios != tty->driver->other->termios[idx]) { | ||
1601 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | ||
1602 | "not o_termios for (%s)\n", | ||
1603 | idx, tty->name); | ||
1604 | return -1; | ||
1605 | } | ||
1606 | if (o_tty->link != tty) { | ||
1607 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | ||
1608 | return -1; | ||
1609 | } | ||
1610 | } | ||
1611 | #endif | ||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | /** | ||
1560 | * tty_release - vfs callback for close | 1616 | * tty_release - vfs callback for close |
1561 | * @inode: inode of tty | 1617 | * @inode: inode of tty |
1562 | * @filp: file pointer for handle to tty | 1618 | * @filp: file pointer for handle to tty |
@@ -1598,59 +1654,16 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1598 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; | 1654 | devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; |
1599 | o_tty = tty->link; | 1655 | o_tty = tty->link; |
1600 | 1656 | ||
1601 | #ifdef TTY_PARANOIA_CHECK | 1657 | if (tty_release_checks(tty, o_tty, idx)) { |
1602 | if (idx < 0 || idx >= tty->driver->num) { | ||
1603 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | ||
1604 | "free (%s)\n", tty->name); | ||
1605 | tty_unlock(); | 1658 | tty_unlock(); |
1606 | return 0; | 1659 | return 0; |
1607 | } | 1660 | } |
1608 | if (!devpts) { | ||
1609 | if (tty != tty->driver->ttys[idx]) { | ||
1610 | tty_unlock(); | ||
1611 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | ||
1612 | "for (%s)\n", idx, tty->name); | ||
1613 | return 0; | ||
1614 | } | ||
1615 | if (tty->termios != tty->driver->termios[idx]) { | ||
1616 | tty_unlock(); | ||
1617 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | ||
1618 | "for (%s)\n", | ||
1619 | idx, tty->name); | ||
1620 | return 0; | ||
1621 | } | ||
1622 | } | ||
1623 | #endif | ||
1624 | 1661 | ||
1625 | #ifdef TTY_DEBUG_HANGUP | 1662 | #ifdef TTY_DEBUG_HANGUP |
1626 | printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...", | 1663 | printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...", |
1627 | tty_name(tty, buf), tty->count); | 1664 | tty_name(tty, buf), tty->count); |
1628 | #endif | 1665 | #endif |
1629 | 1666 | ||
1630 | #ifdef TTY_PARANOIA_CHECK | ||
1631 | if (tty->driver->other && | ||
1632 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | ||
1633 | if (o_tty != tty->driver->other->ttys[idx]) { | ||
1634 | tty_unlock(); | ||
1635 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | ||
1636 | "not o_tty for (%s)\n", | ||
1637 | idx, tty->name); | ||
1638 | return 0 ; | ||
1639 | } | ||
1640 | if (o_tty->termios != tty->driver->other->termios[idx]) { | ||
1641 | tty_unlock(); | ||
1642 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | ||
1643 | "not o_termios for (%s)\n", | ||
1644 | idx, tty->name); | ||
1645 | return 0; | ||
1646 | } | ||
1647 | if (o_tty->link != tty) { | ||
1648 | tty_unlock(); | ||
1649 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | ||
1650 | return 0; | ||
1651 | } | ||
1652 | } | ||
1653 | #endif | ||
1654 | if (tty->ops->close) | 1667 | if (tty->ops->close) |
1655 | tty->ops->close(tty, filp); | 1668 | tty->ops->close(tty, filp); |
1656 | 1669 | ||