Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp776659ybb; Wed, 1 Apr 2020 09:24:58 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvx5DGQx2Mnbc+OS68wuoKRCyNBUOSwBCkjmfTsTwgKeR9oQE6oRKiaY4aHuCqIFlGcRh3D X-Received: by 2002:a05:6830:15cf:: with SMTP id j15mr18435013otr.292.1585758298758; Wed, 01 Apr 2020 09:24:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585758298; cv=none; d=google.com; s=arc-20160816; b=oa6p63wrNDLTdPb38dEQ4IbN4zNGfh6qWxyR7gLZXWFXmJ3XnU01vLd+monxPJ905S 5v/+R2O3FFd8GMimDNaL8vp8Ne2T54sVfioQbGywOV31ruYFn0gvBohkCUcrAZ8J5+nx mwZ5rY3oOKx/uWNPzki3cH2KOV/j5JjvZyQKAjQa3fbHV9w8BreuOVNPa46V4pP5hC/C 3tHNNhEm6/z2F6wRzi5vOOo6aInZc06YriV8+G68gGYijr4R7uD3qAQ+sg9TUrrDNizC Ij3qC8pWV1+J9IqBksyN7vigV3EjRhRSmTGkaZDxZqz/rnq1H9NJ0BDmsBcBk5KS6QN2 jhHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=k/SWcUQUufYTFd37M0qCPruAfao2zXOU5A9CpN11olE=; b=0AQ+jIAVjpvupMvrGkcoYgo4NjT8Dl4oAmwW1qHIfN0VB9prXfx/gcJa/YOHvQeOmA Etj9NfFaPoO+WXYwsrNLKX0/kje77pmoVsZ1/+lw50QELyQH+B3UzHnSilWRUamZ14Qq b/A4lGFwCCECG8QweJzsfmyJuhL/GkN+CU5YOy6pbzQkgyncL5CIJz0Dupl2Hp8ad+uX DgKqn1yeOigk5vK5B7RC2AmFLksuSlRW2pwed9FTQZ9Enq07NvqBotYDz3Bu7sRkdoqq rwRA2gfZa/CTUmCL6gLDofydJImZK/rz3MvMONjTVZUmVFiym1lGRV3TgErCcGhMi26k Emtg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=YqpB0QKq; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n4si1081551oie.121.2020.04.01.09.24.46; Wed, 01 Apr 2020 09:24:58 -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=@kernel.org header.s=default header.b=YqpB0QKq; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387514AbgDAQWj (ORCPT + 99 others); Wed, 1 Apr 2020 12:22:39 -0400 Received: from mail.kernel.org ([198.145.29.99]:45700 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732246AbgDAQWh (ORCPT ); Wed, 1 Apr 2020 12:22:37 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 195E6212CC; Wed, 1 Apr 2020 16:22:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1585758155; bh=xEtiESbTIcESJ4xqcCwq5ZZHvMgmrv9aSMzI+0ZLmPo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YqpB0QKqrS323/dWujsOJNgBGBEhYzxHuBQkjNtRnMjy9iLYQjtmqlML2ew9+dIl3 mjA96iTZgQeaxv9qFr7YJ4yTrdQKQvV9W2CP2U/CXe3FAgyGN6s2Mrjr6RherdnzEn 88XIL5zdnLaHbyV4O8f9Aa/hBcJvlN6guPcsE2Lk= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jiri Slaby , Eric Biggers Subject: [PATCH 5.4 09/27] vt: vt_ioctl: fix use-after-free in vt_in_use() Date: Wed, 1 Apr 2020 18:17:37 +0200 Message-Id: <20200401161422.995544906@linuxfoundation.org> X-Mailer: git-send-email 2.26.0 In-Reply-To: <20200401161414.352722470@linuxfoundation.org> References: <20200401161414.352722470@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Eric Biggers commit 7cf64b18b0b96e751178b8d0505d8466ff5a448f upstream. vt_in_use() dereferences console_driver->ttys[i] without proper locking. This is broken because the tty can be closed and freed concurrently. We could fix this by using 'READ_ONCE(console_driver->ttys[i]) != NULL' and skipping the check of tty_struct::count. But, looking at console_driver->ttys[i] isn't really appropriate anyway because even if it is NULL the tty can still be in the process of being closed. Instead, fix it by making vt_in_use() require console_lock() and check whether the vt is allocated and has port refcount > 1. This works since following the patch "vt: vt_ioctl: fix VT_DISALLOCATE freeing in-use virtual console" the port refcount is incremented while the vt is open. Reproducer (very unreliable, but it worked for me after a few minutes): #include #include int main() { int fd, nproc; struct vt_stat state; char ttyname[16]; fd = open("/dev/tty10", O_RDONLY); for (nproc = 1; nproc < 8; nproc *= 2) fork(); for (;;) { sprintf(ttyname, "/dev/tty%d", rand() % 8); close(open(ttyname, O_RDONLY)); ioctl(fd, VT_GETSTATE, &state); } } KASAN report: BUG: KASAN: use-after-free in vt_in_use drivers/tty/vt/vt_ioctl.c:48 [inline] BUG: KASAN: use-after-free in vt_ioctl+0x1ad3/0x1d70 drivers/tty/vt/vt_ioctl.c:657 Read of size 4 at addr ffff888065722468 by task syz-vt2/132 CPU: 0 PID: 132 Comm: syz-vt2 Not tainted 5.6.0-rc5-00130-g089b6d3654916 #13 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20191223_100556-anatol 04/01/2014 Call Trace: [...] vt_in_use drivers/tty/vt/vt_ioctl.c:48 [inline] vt_ioctl+0x1ad3/0x1d70 drivers/tty/vt/vt_ioctl.c:657 tty_ioctl+0x9db/0x11b0 drivers/tty/tty_io.c:2660 [...] Allocated by task 136: [...] kzalloc include/linux/slab.h:669 [inline] alloc_tty_struct+0x96/0x8a0 drivers/tty/tty_io.c:2982 tty_init_dev+0x23/0x350 drivers/tty/tty_io.c:1334 tty_open_by_driver drivers/tty/tty_io.c:1987 [inline] tty_open+0x3ca/0xb30 drivers/tty/tty_io.c:2035 [...] Freed by task 41: [...] kfree+0xbf/0x200 mm/slab.c:3757 free_tty_struct+0x8d/0xb0 drivers/tty/tty_io.c:177 release_one_tty+0x22d/0x2f0 drivers/tty/tty_io.c:1468 process_one_work+0x7f1/0x14b0 kernel/workqueue.c:2264 worker_thread+0x8b/0xc80 kernel/workqueue.c:2410 [...] Fixes: 4001d7b7fc27 ("vt: push down the tty lock so we can see what is left to tackle") Cc: # v3.4+ Acked-by: Jiri Slaby Signed-off-by: Eric Biggers Link: https://lore.kernel.org/r/20200322034305.210082-3-ebiggers@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt_ioctl.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -43,9 +43,15 @@ bool vt_dont_switch; static inline bool vt_in_use(unsigned int i) { - extern struct tty_driver *console_driver; + const struct vc_data *vc = vc_cons[i].d; - return console_driver->ttys[i] && console_driver->ttys[i]->count; + /* + * console_lock must be held to prevent the vc from being deallocated + * while we're checking whether it's in-use. + */ + WARN_CONSOLE_UNLOCKED(); + + return vc && kref_read(&vc->port.kref) > 1; } static inline bool vt_busy(int i) @@ -643,15 +649,16 @@ int vt_ioctl(struct tty_struct *tty, struct vt_stat __user *vtstat = up; unsigned short state, mask; - /* Review: FIXME: Console lock ? */ if (put_user(fg_console + 1, &vtstat->v_active)) ret = -EFAULT; else { state = 1; /* /dev/tty0 is always open */ + console_lock(); /* required by vt_in_use() */ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) if (vt_in_use(i)) state |= mask; + console_unlock(); ret = put_user(state, &vtstat->v_state); } break; @@ -661,10 +668,11 @@ int vt_ioctl(struct tty_struct *tty, * Returns the first available (non-opened) console. */ case VT_OPENQRY: - /* FIXME: locking ? - but then this is a stupid API */ + console_lock(); /* required by vt_in_use() */ for (i = 0; i < MAX_NR_CONSOLES; ++i) if (!vt_in_use(i)) break; + console_unlock(); uival = i < MAX_NR_CONSOLES ? (i+1) : -1; goto setint;