| From 9ce119f318ba1a07c29149301f1544b6c4bea52a Mon Sep 17 00:00:00 2001 |
| From: Peter Hurley <peter@hurleysoftware.com> |
| Date: Fri, 27 Nov 2015 14:25:08 -0500 |
| Subject: tty: Fix GPF in flush_to_ldisc() |
| |
| commit 9ce119f318ba1a07c29149301f1544b6c4bea52a upstream. |
| |
| A line discipline which does not define a receive_buf() method can |
| can cause a GPF if data is ever received [1]. Oddly, this was known |
| to the author of n_tracesink in 2011, but never fixed. |
| |
| [1] GPF report |
| BUG: unable to handle kernel NULL pointer dereference at (null) |
| IP: [< (null)>] (null) |
| PGD 3752d067 PUD 37a7b067 PMD 0 |
| Oops: 0010 [#1] SMP KASAN |
| Modules linked in: |
| CPU: 2 PID: 148 Comm: kworker/u10:2 Not tainted 4.4.0-rc2+ #51 |
| Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 |
| Workqueue: events_unbound flush_to_ldisc |
| task: ffff88006da94440 ti: ffff88006db60000 task.ti: ffff88006db60000 |
| RIP: 0010:[<0000000000000000>] [< (null)>] (null) |
| RSP: 0018:ffff88006db67b50 EFLAGS: 00010246 |
| RAX: 0000000000000102 RBX: ffff88003ab32f88 RCX: 0000000000000102 |
| RDX: 0000000000000000 RSI: ffff88003ab330a6 RDI: ffff88003aabd388 |
| RBP: ffff88006db67c48 R08: ffff88003ab32f9c R09: ffff88003ab31fb0 |
| R10: ffff88003ab32fa8 R11: 0000000000000000 R12: dffffc0000000000 |
| R13: ffff88006db67c20 R14: ffffffff863df820 R15: ffff88003ab31fb8 |
| FS: 0000000000000000(0000) GS:ffff88006dc00000(0000) knlGS:0000000000000000 |
| CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b |
| CR2: 0000000000000000 CR3: 0000000037938000 CR4: 00000000000006e0 |
| Stack: |
| ffffffff829f46f1 ffff88006da94bf8 ffff88006da94bf8 0000000000000000 |
| ffff88003ab31fb0 ffff88003aabd438 ffff88003ab31ff8 ffff88006430fd90 |
| ffff88003ab32f9c ffffed0007557a87 1ffff1000db6cf78 ffff88003ab32078 |
| Call Trace: |
| [<ffffffff8127cf91>] process_one_work+0x8f1/0x17a0 kernel/workqueue.c:2030 |
| [<ffffffff8127df14>] worker_thread+0xd4/0x1180 kernel/workqueue.c:2162 |
| [<ffffffff8128faaf>] kthread+0x1cf/0x270 drivers/block/aoe/aoecmd.c:1302 |
| [<ffffffff852a7c2f>] ret_from_fork+0x3f/0x70 arch/x86/entry/entry_64.S:468 |
| Code: Bad RIP value. |
| RIP [< (null)>] (null) |
| RSP <ffff88006db67b50> |
| CR2: 0000000000000000 |
| ---[ end trace a587f8947e54d6ea ]--- |
| |
| Reported-by: Dmitry Vyukov <dvyukov@google.com> |
| Signed-off-by: Peter Hurley <peter@hurleysoftware.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| [lizf: Backportd to 3.4: adjust context] |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/tty/tty_buffer.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/tty/tty_buffer.c |
| +++ b/drivers/tty/tty_buffer.c |
| @@ -443,7 +443,8 @@ static void flush_to_ldisc(struct work_s |
| flag_buf = head->flag_buf_ptr + head->read; |
| head->read += count; |
| spin_unlock_irqrestore(&tty->buf.lock, flags); |
| - disc->ops->receive_buf(tty, char_buf, |
| + if (disc->ops->receive_buf) |
| + disc->ops->receive_buf(tty, char_buf, |
| flag_buf, count); |
| spin_lock_irqsave(&tty->buf.lock, flags); |
| } |