diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-11-08 14:12:33 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-11-09 18:14:29 +0100 |
commit | 3ed1cfb2cee4355ddef49489897bfe474daeeaec (patch) | |
tree | 928c0b423d80bdba2768908fd6ede053d1f07c35 /drivers/accessibility | |
parent | speakup: Fix clearing selection in safe context (diff) | |
download | linux-3ed1cfb2cee4355ddef49489897bfe474daeeaec.tar.xz linux-3ed1cfb2cee4355ddef49489897bfe474daeeaec.zip |
speakup ttyio: Do not schedule() in ttyio_in_nowait
With the ltlk and spkout drivers, the index read function, i.e.
in_nowait, is getting called from the read_all_doc mechanism, from
the timer softirq:
Call Trace:
<IRQ>
dump_stack+0x71/0x98
dequeue_task_idle+0x1f/0x28
__schedule+0x167/0x5d6
? trace_hardirqs_on+0x2e/0x3a
? usleep_range+0x7f/0x7f
schedule+0x8a/0xae
schedule_timeout+0xb1/0xea
? del_timer_sync+0x31/0x31
do_wait_for_common+0xba/0x12b
? wake_up_q+0x45/0x45
wait_for_common+0x37/0x50
ttyio_in+0x2a/0x6b
spk_ttyio_in_nowait+0xc/0x13
spk_get_index_count+0x20/0x93
cursor_done+0x1c6/0x4c6
? read_all_doc+0xb1/0xb1
call_timer_fn+0x89/0x140
run_timer_softirq+0x164/0x1a5
? read_all_doc+0xb1/0xb1
? hrtimer_forward+0x7b/0x87
? timerqueue_add+0x62/0x68
? enqueue_hrtimer+0x95/0x9f
__do_softirq+0x181/0x31f
irq_exit+0x6a/0x86
smp_apic_timer_interrupt+0x15e/0x183
apic_timer_interrupt+0xf/0x20
</IRQ>
We thus should not schedule() at all, even with timeout == 0, this
crashes the kernel. We can however use try_wait_for_completion()
instead of wait_for_completion_timeout(0).
Cc: stable@vger.kernel.org
Reported-by: John Covici <covici@ccs.covici.com>
Tested-by: John Covici <covici@ccs.covici.com>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Link: https://lore.kernel.org/r/20201108131233.tadycr73sxlvodgo@function
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/accessibility')
-rw-r--r-- | drivers/accessibility/speakup/spk_ttyio.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/accessibility/speakup/spk_ttyio.c b/drivers/accessibility/speakup/spk_ttyio.c index a831ff64f8ba..ecc39983e946 100644 --- a/drivers/accessibility/speakup/spk_ttyio.c +++ b/drivers/accessibility/speakup/spk_ttyio.c @@ -298,11 +298,13 @@ static unsigned char ttyio_in(int timeout) struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data; char rv; - if (wait_for_completion_timeout(&ldisc_data->completion, + if (!timeout) { + if (!try_wait_for_completion(&ldisc_data->completion)) + return 0xff; + } else if (wait_for_completion_timeout(&ldisc_data->completion, usecs_to_jiffies(timeout)) == 0) { - if (timeout) - pr_warn("spk_ttyio: timeout (%d) while waiting for input\n", - timeout); + pr_warn("spk_ttyio: timeout (%d) while waiting for input\n", + timeout); return 0xff; } |