diff options
Diffstat (limited to 'drivers/char/tty_ldisc.c')
| -rw-r--r-- | drivers/char/tty_ldisc.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819b..3f653f7d849f 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 | ||
| @@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
| 443 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
| 444 | { | 446 | { |
| 445 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
| 446 | if (ld->ops->open) | 448 | if (ld->ops->open) { |
| 447 | return ld->ops->open(tty); | 449 | int ret; |
| 450 | /* BKL here locks verus a hangup event */ | ||
| 451 | lock_kernel(); | ||
| 452 | ret = ld->ops->open(tty); | ||
| 453 | unlock_kernel(); | ||
| 454 | return ret; | ||
| 455 | } | ||
| 448 | return 0; | 456 | return 0; |
| 449 | } | 457 | } |
| 450 | 458 | ||
| @@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 545 | if (IS_ERR(new_ldisc)) | 553 | if (IS_ERR(new_ldisc)) |
| 546 | return PTR_ERR(new_ldisc); | 554 | return PTR_ERR(new_ldisc); |
| 547 | 555 | ||
| 556 | lock_kernel(); | ||
| 548 | /* | 557 | /* |
| 549 | * We need to look at the tty locking here for pty/tty pairs | 558 | * We need to look at the tty locking here for pty/tty pairs |
| 550 | * when both sides try to change in parallel. | 559 | * when both sides try to change in parallel. |
| @@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 558 | */ | 567 | */ |
| 559 | 568 | ||
| 560 | if (tty->ldisc->ops->num == ldisc) { | 569 | if (tty->ldisc->ops->num == ldisc) { |
| 570 | unlock_kernel(); | ||
| 561 | tty_ldisc_put(new_ldisc); | 571 | tty_ldisc_put(new_ldisc); |
| 562 | return 0; | 572 | return 0; |
| 563 | } | 573 | } |
| 564 | 574 | ||
| 575 | unlock_kernel(); | ||
| 565 | /* | 576 | /* |
| 566 | * Problem: What do we do if this blocks ? | 577 | * Problem: What do we do if this blocks ? |
| 567 | * We could deadlock here | 578 | * We could deadlock here |
| @@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 582 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
| 583 | mutex_lock(&tty->ldisc_mutex); | 594 | mutex_lock(&tty->ldisc_mutex); |
| 584 | } | 595 | } |
| 596 | |||
| 597 | lock_kernel(); | ||
| 598 | |||
| 585 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
| 586 | 600 | ||
| 587 | /* | 601 | /* |
| @@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 592 | tty->receive_room = 0; | 606 | tty->receive_room = 0; |
| 593 | 607 | ||
| 594 | o_ldisc = tty->ldisc; | 608 | o_ldisc = tty->ldisc; |
| 609 | |||
| 610 | unlock_kernel(); | ||
| 595 | /* | 611 | /* |
| 596 | * Make sure we don't change while someone holds a | 612 | * Make sure we don't change while someone holds a |
| 597 | * reference to the line discipline. The TTY_LDISC bit | 613 | * reference to the line discipline. The TTY_LDISC bit |
| @@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 617 | flush_scheduled_work(); | 633 | flush_scheduled_work(); |
| 618 | 634 | ||
| 619 | mutex_lock(&tty->ldisc_mutex); | 635 | mutex_lock(&tty->ldisc_mutex); |
| 636 | lock_kernel(); | ||
| 620 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 637 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
| 621 | /* We were raced by the hangup method. It will have stomped | 638 | /* We were raced by the hangup method. It will have stomped |
| 622 | the ldisc data and closed the ldisc down */ | 639 | the ldisc data and closed the ldisc down */ |
| 623 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
| 624 | mutex_unlock(&tty->ldisc_mutex); | 641 | mutex_unlock(&tty->ldisc_mutex); |
| 625 | tty_ldisc_put(new_ldisc); | 642 | tty_ldisc_put(new_ldisc); |
| 643 | unlock_kernel(); | ||
| 626 | return -EIO; | 644 | return -EIO; |
| 627 | } | 645 | } |
| 628 | 646 | ||
| @@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 664 | if (o_work) | 682 | if (o_work) |
| 665 | schedule_delayed_work(&o_tty->buf.work, 1); | 683 | schedule_delayed_work(&o_tty->buf.work, 1); |
| 666 | mutex_unlock(&tty->ldisc_mutex); | 684 | mutex_unlock(&tty->ldisc_mutex); |
| 685 | unlock_kernel(); | ||
| 667 | return retval; | 686 | return retval; |
| 668 | } | 687 | } |
| 669 | 688 | ||
