Received: by 10.192.165.148 with SMTP id m20csp697190imm; Wed, 25 Apr 2018 06:22:43 -0700 (PDT) X-Google-Smtp-Source: AIpwx49JY6G61bK5vxEAWcJZ7a3ZeJO3qae9AfEh2+CYPenhhJzUogSM9sYa1wXAXbfeNN4lrx5U X-Received: by 10.99.99.133 with SMTP id x127mr23478361pgb.50.1524662563440; Wed, 25 Apr 2018 06:22:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524662563; cv=none; d=google.com; s=arc-20160816; b=OHxIFuP0PilWB9zNtRfjsW6Ud9Ni72vWrO+FR8k3k2AttRQTGsWlCiSfOr0XGieV1/ wrAXNuV6WnSjnbilyzx6g++CStYr05sEcLuNdGVmhRyOhpck5qm8UrYDAo5thN8RjxYb 40xXszSqYt2YAxwWTzYZujMqNMHI2rhnTxLSNmnaHV/B9GfBma/bRrxYMY2hLs92sbiS Z6QEe1Dp3+dGOdBwD5C+/68rkuEDNYCYCVsE0WNGauIYWAKbT26bNnonNpP/Z+GJ5uq4 Fff3YN+fZtzC9MvmOh1wFKsEHXPDpKyEdXiS471WKSUp0yzVMFjfoKFhlxcCUMtokf7j pkWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:content-disposition :mime-version:message-id:subject:cc:to:from:date:dkim-signature :arc-authentication-results; bh=KJwnLdTPxcprXTSg50TqWcPIF0FJF16NCUN2AlqmgT4=; b=zAGnVmkCu0lFwBCUka/pldmcqA06OZwm9hNnqlWA1KqHNzePiGm4GfmOvfw4Ri9I8Y Lz+VJ2s/+G4ft8Jw69kdawemd7UgtEcs61OBAA1eaMbXL4OrCtMdN6CtjAgDiahZxN0I eTbj8e5K9ZeTDcHK+VI/hfXP+lt0hJ36dnxtAeGHiC1D9CB5vKiuPHYyqQNU6CygYUWD 9qyY7Liq6600kHeb20iS6WfNltMY8ujuFN8uf4LEQ9QxHlg0LQFxCaT5xs8IFpvmBcSr Tu59Gdg+FUcM2HZ8PizI4RHL27Q6zKPuirSfmLy1KiVALklx9+iAfCIwsaEBpqzUQtSb XSzw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=dPXOujyH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 70-v6si16086740ple.372.2018.04.25.06.22.28; Wed, 25 Apr 2018 06:22:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=dPXOujyH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753971AbeDYNVB (ORCPT + 99 others); Wed, 25 Apr 2018 09:21:01 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:39378 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752276AbeDYNUz (ORCPT ); Wed, 25 Apr 2018 09:20:55 -0400 Received: by mail-pf0-f195.google.com with SMTP id z9so15216999pfe.6 for ; Wed, 25 Apr 2018 06:20:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=KJwnLdTPxcprXTSg50TqWcPIF0FJF16NCUN2AlqmgT4=; b=dPXOujyHGqjc654G4TZe7QnJzXqdchSCYQUThzwpXMQVfU/Qb8Fv91fVKtjliKQykL 3KHhCD+JmyOrO0go7xiO00L58fS41WvjqPQ7PJ9h5nh9d3t2g/cjkR4yLMuoq2Y0aX/t UpTSdaVgJUJfdk/jZ4NY1fGVnRhA/4KexKhjEXvPuLksvkAUjhj5yWp6z/nw+JPwDlGn L5nvH85IGKe9vV4i4Q/Of80sFOIJ+TyxvbdzLJBDgXMM8UcNIZGY1JtuD+gDHScKSrag /cC9MmK18IhEv72hfPaa0ihX+w3uTyeBpfTTBYrQr6AwA3vB0UOMZ/vPG5lcrO6iAc54 r55g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=KJwnLdTPxcprXTSg50TqWcPIF0FJF16NCUN2AlqmgT4=; b=rpCXWS0R6/NH6ClHNeoZ8hfhU+mVWpdaZ2sOXqm/8ON/mg7EeQKByzW+eY2cqJj3ZI OfptlxJpWvbocqdvYxiJ2+nyF8mjNhREzQaaNQbIyTXFdFg7mBub9dUOMoWxcKtwxao6 n9f/YdVr305DIYpszaWHvTrNJpgl7nSQHl9t7N+cuvsOGUDrr3dLbGuQ0fl1k4b8H2zM JM1hkRpks4+x4oH5/4gmr9JTqAICCN91SyrIR+Cfs8zF7SKQwSsaJ/fqltTFyR0Weqmg EYyWlyOAQhFV4k7vFmh9tDSPxyCef0RIN5j5UPFZYCCnjNO+Lin+7T/elddpYgQy6ap6 /AIw== X-Gm-Message-State: ALQs6tAe2ZsuiTpGn5FwJb97nGOBtPZHcHA1TSCLostNNNrYr+08v8SR xLrlcbeQnJn9j8MFIM+ZnMc= X-Received: by 10.99.36.7 with SMTP id k7mr23859692pgk.63.1524662455247; Wed, 25 Apr 2018 06:20:55 -0700 (PDT) Received: from dragonet.kaist.ac.kr (dragonet.kaist.ac.kr. [143.248.133.220]) by smtp.gmail.com with ESMTPSA id p1sm32815817pfp.48.2018.04.25.06.20.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 25 Apr 2018 06:20:54 -0700 (PDT) Date: Wed, 25 Apr 2018 22:20:50 +0900 From: DaeRyong Jeong To: gregkh@linuxfoundation.org, jslaby@suse.com Cc: byoungyoung@purdue.edu, kt0755@gmail.com, bammanag@purdue.edu, linux-kernel@vger.kernel.org Subject: [PATCH] tty: Fix data race in tty_insert_flip_string_fixed_flag Message-ID: <20180425132047.GA20337@dragonet.kaist.ac.kr> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org tty_insert_flip_string_fixed_flag() copies chars to the buffer indicated by th->used and updates tb->used. But tty_insert_flip_string_fixed_flag() can be executed concurrently and tb->used can be updated improperly. It leads slab-out-of-bound write in tty_insert_flip_string_fixed_flag or slab-out-of-bounds read in flush_to_ldisc 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 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 Acquire tty->atomic_write_lock by calling tty_write_lock() before __start_tty() since __start_tty() can sends frames. Signed-off-by: DaeRyong Jeong --- drivers/tty/tty_io.c | 16 +++++++++------- drivers/tty/tty_ioctl.c | 5 +++++ include/linux/tty.h | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 63114ea35ec1..41f83bd4cc40 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -873,13 +873,15 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, return i; } -static void tty_write_unlock(struct tty_struct *tty) +void tty_write_unlock(struct tty_struct *tty, int wakeup) { mutex_unlock(&tty->atomic_write_lock); - wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); + if (wakeup) { + wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); + } } -static int tty_write_lock(struct tty_struct *tty, int ndelay) +int tty_write_lock(struct tty_struct *tty, int ndelay) { if (!mutex_trylock(&tty->atomic_write_lock)) { if (ndelay) @@ -973,7 +975,7 @@ static inline ssize_t do_tty_write( ret = written; } out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return ret; } @@ -997,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg) if (tty->ops->write && tty->count > 0) tty->ops->write(tty, msg, strlen(msg)); tty_unlock(tty); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); } return; } @@ -1092,7 +1094,7 @@ int tty_send_xchar(struct tty_struct *tty, char ch) if (was_stopped) stop_tty(tty); up_read(&tty->termios_rwsem); - tty_write_unlock(tty); + tty_write_unlock(tty, 1); return 0; } @@ -2395,7 +2397,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration) msleep_interruptible(duration); retval = tty->ops->break_ctl(tty, 0); out: - tty_write_unlock(tty); + tty_write_unlock(tty, 1); if (signal_pending(current)) retval = -EINTR; } diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index d9b561d89432..a54ab91aec90 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -911,12 +911,17 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, spin_unlock_irq(&tty->flow_lock); break; case TCOON: + if (tty_write_lock(tty, 0) < 0) + return -ERESTARTSYS; + spin_lock_irq(&tty->flow_lock); if (tty->flow_stopped) { tty->flow_stopped = 0; __start_tty(tty); } spin_unlock_irq(&tty->flow_lock); + + tty_write_unlock(tty, 0); break; case TCIOFF: if (STOP_CHAR(tty) != __DISABLED_CHAR) diff --git a/include/linux/tty.h b/include/linux/tty.h index 47f8af22f216..9b18393d2f95 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -458,6 +458,8 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty) return tty; } +void tty_write_unlock(struct tty_struct *tty, int wakeup); +int tty_write_lock(struct tty_struct *tty, int ndelay); extern const char *tty_driver_name(const struct tty_struct *tty); extern void tty_wait_until_sent(struct tty_struct *tty, long timeout); extern int __tty_check_change(struct tty_struct *tty, int sig); -- 2.14.3