Skip to content

Commit 9a9e6b4

Browse files
sthibaulksacilotto
authored andcommitted
speakup: Do not let the line discipline be used several times
BugLink: https://bugs.launchpad.net/bugs/1908561 commit d412275 upstream. Speakup has only one speakup_tty variable to store the tty it is managing. This makes sense since its codebase currently assumes that there is only one user who controls the screen reading. That however means that we have to forbid using the line discipline several times, otherwise the second closure would try to free a NULL ldisc_data, leading to general protection fault: 0000 [#1] SMP KASAN PTI RIP: 0010:spk_ttyio_ldisc_close+0x2c/0x60 Call Trace: tty_ldisc_release+0xa2/0x340 tty_release_struct+0x17/0xd0 tty_release+0x9d9/0xcc0 __fput+0x231/0x740 task_work_run+0x12c/0x1a0 do_exit+0x9b5/0x2230 ? release_task+0x1240/0x1240 ? __do_page_fault+0x562/0xa30 do_group_exit+0xd5/0x2a0 __x64_sys_exit_group+0x35/0x40 do_syscall_64+0x89/0x2b0 ? page_fault+0x8/0x30 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Cc: stable@vger.kernel.org Reported-by: 秦世松 <qinshisong1205@gmail.com> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Tested-by: Shisong Qin <qinshisong1205@gmail.com> Link: https://lore.kernel.org/r/20201110183541.fzgnlwhjpgqzjeth@function Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Ian May <ian.may@canonical.com>
1 parent cf58cd9 commit 9a9e6b4

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

drivers/staging/speakup/spk_ttyio.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,25 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
4949

5050
if (!tty->ops->write)
5151
return -EOPNOTSUPP;
52+
53+
mutex_lock(&speakup_tty_mutex);
54+
if (speakup_tty) {
55+
mutex_unlock(&speakup_tty_mutex);
56+
return -EBUSY;
57+
}
5258
speakup_tty = tty;
5359

5460
ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL);
55-
if (!ldisc_data)
61+
if (!ldisc_data) {
62+
speakup_tty = NULL;
63+
mutex_unlock(&speakup_tty_mutex);
5664
return -ENOMEM;
65+
}
5766

5867
init_completion(&ldisc_data->completion);
5968
ldisc_data->buf_free = true;
6069
speakup_tty->disc_data = ldisc_data;
70+
mutex_unlock(&speakup_tty_mutex);
6171

6272
return 0;
6373
}

0 commit comments

Comments
 (0)