lkml.org 
[lkml]   [2018]   [Aug]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.17 195/336] tty: Fix data race in tty_insert_flip_string_fixed_flag
    Date
    4.17-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: DaeRyong Jeong <threeearcat@gmail.com>

    [ Upstream commit b6da31b2c07c46f2dcad1d86caa835227a16d9ff ]

    Unlike normal serials, in pty layer, there is no guarantee that multiple
    threads don't insert input characters at the same time. If it is happened,
    tty_insert_flip_string_fixed_flag can be executed concurrently. This can
    lead slab out-of-bounds write in tty_insert_flip_string_fixed_flag.

    Call sequences are as follows.
    CPU0 CPU1
    n_tty_ioctl_helper n_tty_ioctl_helper
    __start_tty tty_send_xchar
    tty_wakeup pty_write
    n_hdlc_tty_wakeup tty_insert_flip_string
    n_hdlc_send_frames tty_insert_flip_string_fixed_flag
    pty_write
    tty_insert_flip_string
    tty_insert_flip_string_fixed_flag

    To fix the race, acquire port->lock in pty_write() before it inserts input
    characters to tty buffer. It prevents multiple threads from inserting
    input characters concurrently.

    The crash log is as follows:
    BUG: KASAN: slab-out-of-bounds in tty_insert_flip_string_fixed_flag+0xb5/
    0x130 drivers/tty/tty_buffer.c:316 at addr ffff880114fcc121
    Write of size 1792 by task syz-executor0/30017
    CPU: 1 PID: 30017 Comm: syz-executor0 Not tainted 4.8.0 #1
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
    BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
    0000000000000000 ffff88011638f888 ffffffff81694cc3 ffff88007d802140
    ffff880114fcb300 ffff880114fcc300 ffff880114fcb300 ffff88011638f8b0
    ffffffff8130075c ffff88011638f940 ffff88007d802140 ffff880194fcc121
    Call Trace:
    __dump_stack lib/dump_stack.c:15 [inline]
    dump_stack+0xb3/0x110 lib/dump_stack.c:51
    kasan_object_err+0x1c/0x70 mm/kasan/report.c:156
    print_address_description mm/kasan/report.c:194 [inline]
    kasan_report_error+0x1f7/0x4e0 mm/kasan/report.c:283
    kasan_report+0x36/0x40 mm/kasan/report.c:303
    check_memory_region_inline mm/kasan/kasan.c:292 [inline]
    check_memory_region+0x13e/0x1a0 mm/kasan/kasan.c:299
    memcpy+0x37/0x50 mm/kasan/kasan.c:335
    tty_insert_flip_string_fixed_flag+0xb5/0x130 drivers/tty/tty_buffer.c:316
    tty_insert_flip_string include/linux/tty_flip.h:35 [inline]
    pty_write+0x7f/0xc0 drivers/tty/pty.c:115
    n_hdlc_send_frames+0x1d4/0x3b0 drivers/tty/n_hdlc.c:419
    n_hdlc_tty_wakeup+0x73/0xa0 drivers/tty/n_hdlc.c:496
    tty_wakeup+0x92/0xb0 drivers/tty/tty_io.c:601
    __start_tty.part.26+0x66/0x70 drivers/tty/tty_io.c:1018
    __start_tty+0x34/0x40 drivers/tty/tty_io.c:1013
    n_tty_ioctl_helper+0x146/0x1e0 drivers/tty/tty_ioctl.c:1138
    n_hdlc_tty_ioctl+0xb3/0x2b0 drivers/tty/n_hdlc.c:794
    tty_ioctl+0xa85/0x16d0 drivers/tty/tty_io.c:2992
    vfs_ioctl fs/ioctl.c:43 [inline]
    do_vfs_ioctl+0x13e/0xba0 fs/ioctl.c:679
    SYSC_ioctl fs/ioctl.c:694 [inline]
    SyS_ioctl+0x8f/0xc0 fs/ioctl.c:685
    entry_SYSCALL_64_fastpath+0x1f/0xbd

    Signed-off-by: DaeRyong Jeong <threeearcat@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/tty/pty.c | 3 +++
    1 file changed, 3 insertions(+)

    --- a/drivers/tty/pty.c
    +++ b/drivers/tty/pty.c
    @@ -110,16 +110,19 @@ static void pty_unthrottle(struct tty_st
    static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
    {
    struct tty_struct *to = tty->link;
    + unsigned long flags;

    if (tty->stopped)
    return 0;

    if (c > 0) {
    + spin_lock_irqsave(&to->port->lock, flags);
    /* Stuff the data into the input queue of the other end */
    c = tty_insert_flip_string(to->port, buf, c);
    /* And shovel */
    if (c)
    tty_flip_buffer_push(to->port);
    + spin_unlock_irqrestore(&to->port->lock, flags);
    }
    return c;
    }

    \
     
     \ /
      Last update: 2018-08-01 19:53    [W:4.283 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site