diff options
-rw-r--r-- | drivers/char/pty.c | 2 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 141 | ||||
-rw-r--r-- | drivers/char/tty_ldisc.c | 13 | ||||
-rw-r--r-- | include/linux/tty.h | 2 |
4 files changed, 95 insertions, 63 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d86c0bc05c1c..385c44b3034f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
659 | if (!retval) | 659 | if (!retval) |
660 | return 0; | 660 | return 0; |
661 | out1: | 661 | out1: |
662 | tty_release_dev(filp); | 662 | tty_release(inode, filp); |
663 | return retval; | 663 | return retval; |
664 | out: | 664 | out: |
665 | devpts_kill_index(inode, index); | 665 | devpts_kill_index(inode, index); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59499ee0fe6a..1e2413093615 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *, | |||
142 | size_t, loff_t *); | 142 | size_t, loff_t *); |
143 | static unsigned int tty_poll(struct file *, poll_table *); | 143 | static unsigned int tty_poll(struct file *, poll_table *); |
144 | static int tty_open(struct inode *, struct file *); | 144 | static int tty_open(struct inode *, struct file *); |
145 | static int tty_release(struct inode *, struct file *); | ||
146 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 145 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
147 | #ifdef CONFIG_COMPAT | 146 | #ifdef CONFIG_COMPAT |
148 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, | 147 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, |
@@ -1017,14 +1016,16 @@ out: | |||
1017 | 1016 | ||
1018 | void tty_write_message(struct tty_struct *tty, char *msg) | 1017 | void tty_write_message(struct tty_struct *tty, char *msg) |
1019 | { | 1018 | { |
1020 | lock_kernel(); | ||
1021 | if (tty) { | 1019 | if (tty) { |
1022 | mutex_lock(&tty->atomic_write_lock); | 1020 | mutex_lock(&tty->atomic_write_lock); |
1023 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) | 1021 | lock_kernel(); |
1022 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | ||
1023 | unlock_kernel(); | ||
1024 | tty->ops->write(tty, msg, strlen(msg)); | 1024 | tty->ops->write(tty, msg, strlen(msg)); |
1025 | } else | ||
1026 | unlock_kernel(); | ||
1025 | tty_write_unlock(tty); | 1027 | tty_write_unlock(tty); |
1026 | } | 1028 | } |
1027 | unlock_kernel(); | ||
1028 | return; | 1029 | return; |
1029 | } | 1030 | } |
1030 | 1031 | ||
@@ -1202,14 +1203,21 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
1202 | struct tty_struct *tty) | 1203 | struct tty_struct *tty) |
1203 | { | 1204 | { |
1204 | int idx = tty->index; | 1205 | int idx = tty->index; |
1206 | int ret; | ||
1205 | 1207 | ||
1206 | if (driver->ops->install) | 1208 | if (driver->ops->install) { |
1207 | return driver->ops->install(driver, tty); | 1209 | lock_kernel(); |
1210 | ret = driver->ops->install(driver, tty); | ||
1211 | unlock_kernel(); | ||
1212 | return ret; | ||
1213 | } | ||
1208 | 1214 | ||
1209 | if (tty_init_termios(tty) == 0) { | 1215 | if (tty_init_termios(tty) == 0) { |
1216 | lock_kernel(); | ||
1210 | tty_driver_kref_get(driver); | 1217 | tty_driver_kref_get(driver); |
1211 | tty->count++; | 1218 | tty->count++; |
1212 | driver->ttys[idx] = tty; | 1219 | driver->ttys[idx] = tty; |
1220 | unlock_kernel(); | ||
1213 | return 0; | 1221 | return 0; |
1214 | } | 1222 | } |
1215 | return -ENOMEM; | 1223 | return -ENOMEM; |
@@ -1302,10 +1310,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1302 | struct tty_struct *tty; | 1310 | struct tty_struct *tty; |
1303 | int retval; | 1311 | int retval; |
1304 | 1312 | ||
1313 | lock_kernel(); | ||
1305 | /* Check if pty master is being opened multiple times */ | 1314 | /* Check if pty master is being opened multiple times */ |
1306 | if (driver->subtype == PTY_TYPE_MASTER && | 1315 | if (driver->subtype == PTY_TYPE_MASTER && |
1307 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) | 1316 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
1317 | unlock_kernel(); | ||
1308 | return ERR_PTR(-EIO); | 1318 | return ERR_PTR(-EIO); |
1319 | } | ||
1320 | unlock_kernel(); | ||
1309 | 1321 | ||
1310 | /* | 1322 | /* |
1311 | * First time open is complex, especially for PTY devices. | 1323 | * First time open is complex, especially for PTY devices. |
@@ -1335,8 +1347,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1335 | * If we fail here just call release_tty to clean up. No need | 1347 | * If we fail here just call release_tty to clean up. No need |
1336 | * to decrement the use counts, as release_tty doesn't care. | 1348 | * to decrement the use counts, as release_tty doesn't care. |
1337 | */ | 1349 | */ |
1338 | 1350 | lock_kernel(); | |
1339 | retval = tty_ldisc_setup(tty, tty->link); | 1351 | retval = tty_ldisc_setup(tty, tty->link); |
1352 | unlock_kernel(); | ||
1340 | if (retval) | 1353 | if (retval) |
1341 | goto release_mem_out; | 1354 | goto release_mem_out; |
1342 | return tty; | 1355 | return tty; |
@@ -1350,7 +1363,9 @@ release_mem_out: | |||
1350 | if (printk_ratelimit()) | 1363 | if (printk_ratelimit()) |
1351 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1364 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1352 | "clearing slot %d\n", idx); | 1365 | "clearing slot %d\n", idx); |
1366 | lock_kernel(); | ||
1353 | release_tty(tty, idx); | 1367 | release_tty(tty, idx); |
1368 | unlock_kernel(); | ||
1354 | return ERR_PTR(retval); | 1369 | return ERR_PTR(retval); |
1355 | } | 1370 | } |
1356 | 1371 | ||
@@ -1464,7 +1479,17 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1464 | tty_kref_put(tty); | 1479 | tty_kref_put(tty); |
1465 | } | 1480 | } |
1466 | 1481 | ||
1467 | /* | 1482 | /** |
1483 | * tty_release - vfs callback for close | ||
1484 | * @inode: inode of tty | ||
1485 | * @filp: file pointer for handle to tty | ||
1486 | * | ||
1487 | * Called the last time each file handle is closed that references | ||
1488 | * this tty. There may however be several such references. | ||
1489 | * | ||
1490 | * Locking: | ||
1491 | * Takes bkl. See tty_release_dev | ||
1492 | * | ||
1468 | * Even releasing the tty structures is a tricky business.. We have | 1493 | * Even releasing the tty structures is a tricky business.. We have |
1469 | * to be very careful that the structures are all released at the | 1494 | * to be very careful that the structures are all released at the |
1470 | * same time, as interrupts might otherwise get the wrong pointers. | 1495 | * same time, as interrupts might otherwise get the wrong pointers. |
@@ -1472,20 +1497,20 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1472 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could | 1497 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could |
1473 | * lead to double frees or releasing memory still in use. | 1498 | * lead to double frees or releasing memory still in use. |
1474 | */ | 1499 | */ |
1475 | void tty_release_dev(struct file *filp) | 1500 | |
1501 | int tty_release(struct inode *inode, struct file *filp) | ||
1476 | { | 1502 | { |
1477 | struct tty_struct *tty, *o_tty; | 1503 | struct tty_struct *tty, *o_tty; |
1478 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1504 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1479 | int devpts; | 1505 | int devpts; |
1480 | int idx; | 1506 | int idx; |
1481 | char buf[64]; | 1507 | char buf[64]; |
1482 | struct inode *inode; | ||
1483 | 1508 | ||
1484 | inode = filp->f_path.dentry->d_inode; | ||
1485 | tty = (struct tty_struct *)filp->private_data; | 1509 | tty = (struct tty_struct *)filp->private_data; |
1486 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1510 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1487 | return; | 1511 | return 0; |
1488 | 1512 | ||
1513 | lock_kernel(); | ||
1489 | check_tty_count(tty, "tty_release_dev"); | 1514 | check_tty_count(tty, "tty_release_dev"); |
1490 | 1515 | ||
1491 | tty_fasync(-1, filp, 0); | 1516 | tty_fasync(-1, filp, 0); |
@@ -1500,19 +1525,22 @@ void tty_release_dev(struct file *filp) | |||
1500 | if (idx < 0 || idx >= tty->driver->num) { | 1525 | if (idx < 0 || idx >= tty->driver->num) { |
1501 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1526 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1502 | "free (%s)\n", tty->name); | 1527 | "free (%s)\n", tty->name); |
1503 | return; | 1528 | unlock_kernel(); |
1529 | return 0; | ||
1504 | } | 1530 | } |
1505 | if (!devpts) { | 1531 | if (!devpts) { |
1506 | if (tty != tty->driver->ttys[idx]) { | 1532 | if (tty != tty->driver->ttys[idx]) { |
1533 | unlock_kernel(); | ||
1507 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1534 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1508 | "for (%s)\n", idx, tty->name); | 1535 | "for (%s)\n", idx, tty->name); |
1509 | return; | 1536 | return 0; |
1510 | } | 1537 | } |
1511 | if (tty->termios != tty->driver->termios[idx]) { | 1538 | if (tty->termios != tty->driver->termios[idx]) { |
1539 | unlock_kernel(); | ||
1512 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1540 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1513 | "for (%s)\n", | 1541 | "for (%s)\n", |
1514 | idx, tty->name); | 1542 | idx, tty->name); |
1515 | return; | 1543 | return 0; |
1516 | } | 1544 | } |
1517 | } | 1545 | } |
1518 | #endif | 1546 | #endif |
@@ -1526,26 +1554,30 @@ void tty_release_dev(struct file *filp) | |||
1526 | if (tty->driver->other && | 1554 | if (tty->driver->other && |
1527 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1555 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1528 | if (o_tty != tty->driver->other->ttys[idx]) { | 1556 | if (o_tty != tty->driver->other->ttys[idx]) { |
1557 | unlock_kernel(); | ||
1529 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1558 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1530 | "not o_tty for (%s)\n", | 1559 | "not o_tty for (%s)\n", |
1531 | idx, tty->name); | 1560 | idx, tty->name); |
1532 | return; | 1561 | return 0 ; |
1533 | } | 1562 | } |
1534 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1563 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1564 | unlock_kernel(); | ||
1535 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1565 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1536 | "not o_termios for (%s)\n", | 1566 | "not o_termios for (%s)\n", |
1537 | idx, tty->name); | 1567 | idx, tty->name); |
1538 | return; | 1568 | return 0; |
1539 | } | 1569 | } |
1540 | if (o_tty->link != tty) { | 1570 | if (o_tty->link != tty) { |
1571 | unlock_kernel(); | ||
1541 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1572 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
1542 | return; | 1573 | return 0; |
1543 | } | 1574 | } |
1544 | } | 1575 | } |
1545 | #endif | 1576 | #endif |
1546 | if (tty->ops->close) | 1577 | if (tty->ops->close) |
1547 | tty->ops->close(tty, filp); | 1578 | tty->ops->close(tty, filp); |
1548 | 1579 | ||
1580 | unlock_kernel(); | ||
1549 | /* | 1581 | /* |
1550 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1582 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1551 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1583 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1568,6 +1600,7 @@ void tty_release_dev(struct file *filp) | |||
1568 | opens on /dev/tty */ | 1600 | opens on /dev/tty */ |
1569 | 1601 | ||
1570 | mutex_lock(&tty_mutex); | 1602 | mutex_lock(&tty_mutex); |
1603 | lock_kernel(); | ||
1571 | tty_closing = tty->count <= 1; | 1604 | tty_closing = tty->count <= 1; |
1572 | o_tty_closing = o_tty && | 1605 | o_tty_closing = o_tty && |
1573 | (o_tty->count <= (pty_master ? 1 : 0)); | 1606 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1598,6 +1631,7 @@ void tty_release_dev(struct file *filp) | |||
1598 | 1631 | ||
1599 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1632 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
1600 | "active!\n", tty_name(tty, buf)); | 1633 | "active!\n", tty_name(tty, buf)); |
1634 | unlock_kernel(); | ||
1601 | mutex_unlock(&tty_mutex); | 1635 | mutex_unlock(&tty_mutex); |
1602 | schedule(); | 1636 | schedule(); |
1603 | } | 1637 | } |
@@ -1661,8 +1695,10 @@ void tty_release_dev(struct file *filp) | |||
1661 | mutex_unlock(&tty_mutex); | 1695 | mutex_unlock(&tty_mutex); |
1662 | 1696 | ||
1663 | /* check whether both sides are closing ... */ | 1697 | /* check whether both sides are closing ... */ |
1664 | if (!tty_closing || (o_tty && !o_tty_closing)) | 1698 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
1665 | return; | 1699 | unlock_kernel(); |
1700 | return 0; | ||
1701 | } | ||
1666 | 1702 | ||
1667 | #ifdef TTY_DEBUG_HANGUP | 1703 | #ifdef TTY_DEBUG_HANGUP |
1668 | printk(KERN_DEBUG "freeing tty structure..."); | 1704 | printk(KERN_DEBUG "freeing tty structure..."); |
@@ -1680,10 +1716,12 @@ void tty_release_dev(struct file *filp) | |||
1680 | /* Make this pty number available for reallocation */ | 1716 | /* Make this pty number available for reallocation */ |
1681 | if (devpts) | 1717 | if (devpts) |
1682 | devpts_kill_index(inode, idx); | 1718 | devpts_kill_index(inode, idx); |
1719 | unlock_kernel(); | ||
1720 | return 0; | ||
1683 | } | 1721 | } |
1684 | 1722 | ||
1685 | /** | 1723 | /** |
1686 | * __tty_open - open a tty device | 1724 | * tty_open - open a tty device |
1687 | * @inode: inode of device file | 1725 | * @inode: inode of device file |
1688 | * @filp: file pointer to tty | 1726 | * @filp: file pointer to tty |
1689 | * | 1727 | * |
@@ -1703,7 +1741,7 @@ void tty_release_dev(struct file *filp) | |||
1703 | * ->siglock protects ->signal/->sighand | 1741 | * ->siglock protects ->signal/->sighand |
1704 | */ | 1742 | */ |
1705 | 1743 | ||
1706 | static int __tty_open(struct inode *inode, struct file *filp) | 1744 | static int tty_open(struct inode *inode, struct file *filp) |
1707 | { | 1745 | { |
1708 | struct tty_struct *tty = NULL; | 1746 | struct tty_struct *tty = NULL; |
1709 | int noctty, retval; | 1747 | int noctty, retval; |
@@ -1720,10 +1758,12 @@ retry_open: | |||
1720 | retval = 0; | 1758 | retval = 0; |
1721 | 1759 | ||
1722 | mutex_lock(&tty_mutex); | 1760 | mutex_lock(&tty_mutex); |
1761 | lock_kernel(); | ||
1723 | 1762 | ||
1724 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1763 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { |
1725 | tty = get_current_tty(); | 1764 | tty = get_current_tty(); |
1726 | if (!tty) { | 1765 | if (!tty) { |
1766 | unlock_kernel(); | ||
1727 | mutex_unlock(&tty_mutex); | 1767 | mutex_unlock(&tty_mutex); |
1728 | return -ENXIO; | 1768 | return -ENXIO; |
1729 | } | 1769 | } |
@@ -1755,12 +1795,14 @@ retry_open: | |||
1755 | goto got_driver; | 1795 | goto got_driver; |
1756 | } | 1796 | } |
1757 | } | 1797 | } |
1798 | unlock_kernel(); | ||
1758 | mutex_unlock(&tty_mutex); | 1799 | mutex_unlock(&tty_mutex); |
1759 | return -ENODEV; | 1800 | return -ENODEV; |
1760 | } | 1801 | } |
1761 | 1802 | ||
1762 | driver = get_tty_driver(device, &index); | 1803 | driver = get_tty_driver(device, &index); |
1763 | if (!driver) { | 1804 | if (!driver) { |
1805 | unlock_kernel(); | ||
1764 | mutex_unlock(&tty_mutex); | 1806 | mutex_unlock(&tty_mutex); |
1765 | return -ENODEV; | 1807 | return -ENODEV; |
1766 | } | 1808 | } |
@@ -1770,6 +1812,7 @@ got_driver: | |||
1770 | tty = tty_driver_lookup_tty(driver, inode, index); | 1812 | tty = tty_driver_lookup_tty(driver, inode, index); |
1771 | 1813 | ||
1772 | if (IS_ERR(tty)) { | 1814 | if (IS_ERR(tty)) { |
1815 | unlock_kernel(); | ||
1773 | mutex_unlock(&tty_mutex); | 1816 | mutex_unlock(&tty_mutex); |
1774 | return PTR_ERR(tty); | 1817 | return PTR_ERR(tty); |
1775 | } | 1818 | } |
@@ -1784,8 +1827,10 @@ got_driver: | |||
1784 | 1827 | ||
1785 | mutex_unlock(&tty_mutex); | 1828 | mutex_unlock(&tty_mutex); |
1786 | tty_driver_kref_put(driver); | 1829 | tty_driver_kref_put(driver); |
1787 | if (IS_ERR(tty)) | 1830 | if (IS_ERR(tty)) { |
1831 | unlock_kernel(); | ||
1788 | return PTR_ERR(tty); | 1832 | return PTR_ERR(tty); |
1833 | } | ||
1789 | 1834 | ||
1790 | filp->private_data = tty; | 1835 | filp->private_data = tty; |
1791 | file_move(filp, &tty->tty_files); | 1836 | file_move(filp, &tty->tty_files); |
@@ -1813,11 +1858,15 @@ got_driver: | |||
1813 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1858 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
1814 | tty->name); | 1859 | tty->name); |
1815 | #endif | 1860 | #endif |
1816 | tty_release_dev(filp); | 1861 | tty_release(inode, filp); |
1817 | if (retval != -ERESTARTSYS) | 1862 | if (retval != -ERESTARTSYS) { |
1863 | unlock_kernel(); | ||
1818 | return retval; | 1864 | return retval; |
1819 | if (signal_pending(current)) | 1865 | } |
1866 | if (signal_pending(current)) { | ||
1867 | unlock_kernel(); | ||
1820 | return retval; | 1868 | return retval; |
1869 | } | ||
1821 | schedule(); | 1870 | schedule(); |
1822 | /* | 1871 | /* |
1823 | * Need to reset f_op in case a hangup happened. | 1872 | * Need to reset f_op in case a hangup happened. |
@@ -1826,8 +1875,11 @@ got_driver: | |||
1826 | filp->f_op = &tty_fops; | 1875 | filp->f_op = &tty_fops; |
1827 | goto retry_open; | 1876 | goto retry_open; |
1828 | } | 1877 | } |
1878 | unlock_kernel(); | ||
1879 | |||
1829 | 1880 | ||
1830 | mutex_lock(&tty_mutex); | 1881 | mutex_lock(&tty_mutex); |
1882 | lock_kernel(); | ||
1831 | spin_lock_irq(¤t->sighand->siglock); | 1883 | spin_lock_irq(¤t->sighand->siglock); |
1832 | if (!noctty && | 1884 | if (!noctty && |
1833 | current->signal->leader && | 1885 | current->signal->leader && |
@@ -1835,44 +1887,13 @@ got_driver: | |||
1835 | tty->session == NULL) | 1887 | tty->session == NULL) |
1836 | __proc_set_tty(current, tty); | 1888 | __proc_set_tty(current, tty); |
1837 | spin_unlock_irq(¤t->sighand->siglock); | 1889 | spin_unlock_irq(¤t->sighand->siglock); |
1890 | unlock_kernel(); | ||
1838 | mutex_unlock(&tty_mutex); | 1891 | mutex_unlock(&tty_mutex); |
1839 | return 0; | 1892 | return 0; |
1840 | } | 1893 | } |
1841 | 1894 | ||
1842 | /* BKL pushdown: scary code avoidance wrapper */ | ||
1843 | static int tty_open(struct inode *inode, struct file *filp) | ||
1844 | { | ||
1845 | int ret; | ||
1846 | |||
1847 | lock_kernel(); | ||
1848 | ret = __tty_open(inode, filp); | ||
1849 | unlock_kernel(); | ||
1850 | return ret; | ||
1851 | } | ||
1852 | 1895 | ||
1853 | 1896 | ||
1854 | |||
1855 | |||
1856 | /** | ||
1857 | * tty_release - vfs callback for close | ||
1858 | * @inode: inode of tty | ||
1859 | * @filp: file pointer for handle to tty | ||
1860 | * | ||
1861 | * Called the last time each file handle is closed that references | ||
1862 | * this tty. There may however be several such references. | ||
1863 | * | ||
1864 | * Locking: | ||
1865 | * Takes bkl. See tty_release_dev | ||
1866 | */ | ||
1867 | |||
1868 | static int tty_release(struct inode *inode, struct file *filp) | ||
1869 | { | ||
1870 | lock_kernel(); | ||
1871 | tty_release_dev(filp); | ||
1872 | unlock_kernel(); | ||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | /** | 1897 | /** |
1877 | * tty_poll - check tty status | 1898 | * tty_poll - check tty status |
1878 | * @filp: file being polled | 1899 | * @filp: file being polled |
@@ -2317,9 +2338,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
2317 | if (get_user(ldisc, p)) | 2338 | if (get_user(ldisc, p)) |
2318 | return -EFAULT; | 2339 | return -EFAULT; |
2319 | 2340 | ||
2320 | lock_kernel(); | ||
2321 | ret = tty_set_ldisc(tty, ldisc); | 2341 | ret = tty_set_ldisc(tty, ldisc); |
2322 | unlock_kernel(); | ||
2323 | 2342 | ||
2324 | return ret; | 2343 | return ret; |
2325 | } | 2344 | } |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819b..d914e77f7f01 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/vt_kern.h> | 34 | #include <linux/vt_kern.h> |
35 | #include <linux/selection.h> | 35 | #include <linux/selection.h> |
36 | 36 | ||
37 | #include <linux/smp_lock.h> /* For the moment */ | ||
38 | |||
37 | #include <linux/kmod.h> | 39 | #include <linux/kmod.h> |
38 | #include <linux/nsproxy.h> | 40 | #include <linux/nsproxy.h> |
39 | 41 | ||
@@ -545,6 +547,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
545 | if (IS_ERR(new_ldisc)) | 547 | if (IS_ERR(new_ldisc)) |
546 | return PTR_ERR(new_ldisc); | 548 | return PTR_ERR(new_ldisc); |
547 | 549 | ||
550 | lock_kernel(); | ||
548 | /* | 551 | /* |
549 | * We need to look at the tty locking here for pty/tty pairs | 552 | * We need to look at the tty locking here for pty/tty pairs |
550 | * when both sides try to change in parallel. | 553 | * when both sides try to change in parallel. |
@@ -558,6 +561,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
558 | */ | 561 | */ |
559 | 562 | ||
560 | if (tty->ldisc->ops->num == ldisc) { | 563 | if (tty->ldisc->ops->num == ldisc) { |
564 | unlock_kernel(); | ||
561 | tty_ldisc_put(new_ldisc); | 565 | tty_ldisc_put(new_ldisc); |
562 | return 0; | 566 | return 0; |
563 | } | 567 | } |
@@ -569,6 +573,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
569 | 573 | ||
570 | tty_wait_until_sent(tty, 0); | 574 | tty_wait_until_sent(tty, 0); |
571 | 575 | ||
576 | unlock_kernel(); | ||
572 | mutex_lock(&tty->ldisc_mutex); | 577 | mutex_lock(&tty->ldisc_mutex); |
573 | 578 | ||
574 | /* | 579 | /* |
@@ -582,6 +587,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
582 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 587 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
583 | mutex_lock(&tty->ldisc_mutex); | 588 | mutex_lock(&tty->ldisc_mutex); |
584 | } | 589 | } |
590 | |||
591 | lock_kernel(); | ||
592 | |||
585 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 593 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
586 | 594 | ||
587 | /* | 595 | /* |
@@ -592,6 +600,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
592 | tty->receive_room = 0; | 600 | tty->receive_room = 0; |
593 | 601 | ||
594 | o_ldisc = tty->ldisc; | 602 | o_ldisc = tty->ldisc; |
603 | |||
604 | unlock_kernel(); | ||
595 | /* | 605 | /* |
596 | * Make sure we don't change while someone holds a | 606 | * Make sure we don't change while someone holds a |
597 | * reference to the line discipline. The TTY_LDISC bit | 607 | * reference to the line discipline. The TTY_LDISC bit |
@@ -617,12 +627,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
617 | flush_scheduled_work(); | 627 | flush_scheduled_work(); |
618 | 628 | ||
619 | mutex_lock(&tty->ldisc_mutex); | 629 | mutex_lock(&tty->ldisc_mutex); |
630 | lock_kernel(); | ||
620 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 631 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
621 | /* We were raced by the hangup method. It will have stomped | 632 | /* We were raced by the hangup method. It will have stomped |
622 | the ldisc data and closed the ldisc down */ | 633 | the ldisc data and closed the ldisc down */ |
623 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 634 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
624 | mutex_unlock(&tty->ldisc_mutex); | 635 | mutex_unlock(&tty->ldisc_mutex); |
625 | tty_ldisc_put(new_ldisc); | 636 | tty_ldisc_put(new_ldisc); |
637 | unlock_kernel(); | ||
626 | return -EIO; | 638 | return -EIO; |
627 | } | 639 | } |
628 | 640 | ||
@@ -664,6 +676,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
664 | if (o_work) | 676 | if (o_work) |
665 | schedule_delayed_work(&o_tty->buf.work, 1); | 677 | schedule_delayed_work(&o_tty->buf.work, 1); |
666 | mutex_unlock(&tty->ldisc_mutex); | 678 | mutex_unlock(&tty->ldisc_mutex); |
679 | unlock_kernel(); | ||
667 | return retval; | 680 | return retval; |
668 | } | 681 | } |
669 | 682 | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index e6da667ba34d..405a9035fe40 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -449,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty, | |||
449 | struct tty_driver *driver, int idx); | 449 | struct tty_driver *driver, int idx); |
450 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 450 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, |
451 | int first_ok); | 451 | int first_ok); |
452 | extern void tty_release_dev(struct file *filp); | 452 | extern int tty_release(struct inode *inode, struct file *filp); |
453 | extern int tty_init_termios(struct tty_struct *tty); | 453 | extern int tty_init_termios(struct tty_struct *tty); |
454 | 454 | ||
455 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); | 455 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); |