Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3380058pxf; Mon, 5 Apr 2021 10:28:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzHbgvku+SvCbGtEYVewnIBUCVfAIceSM651iD1rrFuooNakRCCEdRJV00b2toKTDoIabsf X-Received: by 2002:a17:906:4c45:: with SMTP id d5mr7117445ejw.38.1617643693915; Mon, 05 Apr 2021 10:28:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617643693; cv=none; d=google.com; s=arc-20160816; b=mmieESt9aUtzahpdfLqjR6rzjGigzZNkBFco9y8MTPwWmOmnEQSaKbQQDMBLcUkP7Q T0HqdW5u/qTRymkOOKyqkS3drWOgmCPo3eBUoYC3b5aeT1ONf3WPyiJZzRLSmgw8ZrOL q2RBwsG6cPQ8qvWNNG+Vj3RPgQrfIoJFNcU5A7JCIO8WUifzlaEQsGUvp/iMIb4qRyRA qM+a9Be76vYLWjGuS8jJuSZbAQCvrQ0YTHZDSL6NB6AR3r1wjH3/+WkuQPR0ntqs1Xpk 8J17WYRyOXUFK01fctlorWwBwCICEevTIMi+Q4BiSAls2AoO0UJhqYnkBQE8eP9GNmpZ ad6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=/1jPSt7xJ07JYevQ/kop8SefEqM5/s04PabHNMa4sUE=; b=xs2EkLdGVy3bGc9ObMvfBw0vJsS77ILZNIGY48U++Y4lgqezfciTqoqYOslwtVbSct PicY98wDowk+4quRb8HAXBlxRN4P3w4aM14fNWLO4CVY3vMlGEu0H19Ed1/XLGnb2vNF yHp4nndRnqDBuYXMAnEGxGSimQTfYTZKps3WMyzRLe42CXATSQWPgmBYY4R++CeaFo/+ Bjy9BiGnjzvjOnUwq+8WQVePboWkp8woFQf8mcnl/Z5szgmvojKEsS/+bWar6We/bIoA kKgYbMKqJdibWxTeuQL05OIWgVEGRwdzLsiVxWdGR2z8TwGCPtmhCSDxHI/hu+ASzCWy yyUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="h4Yb/z6A"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id o10si1309512edq.306.2021.04.05.10.27.50; Mon, 05 Apr 2021 10:28:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b="h4Yb/z6A"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240147AbhDEJWP (ORCPT + 99 others); Mon, 5 Apr 2021 05:22:15 -0400 Received: from mail.kernel.org ([198.145.29.99]:39076 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240814AbhDEJRJ (ORCPT ); Mon, 5 Apr 2021 05:17:09 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 22EEB61002; Mon, 5 Apr 2021 09:17:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617614223; bh=+W+vlglgFHzgRJMyRoXng4w6JlgSrTe8jV0YDN8+uTY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h4Yb/z6AK5BarNA/YNfGmTNeD5AHO0N3NNrdI32VoGIgo6AhgQEHZy3HMX6cNNA31 HsvtNCzNhMvrnm0CyYvnX+XR02pZrNG+sa5g3TC3GonDnug9ufTWsC68B4/spEk6dN M1EVpNx2zylV3zKhT68njeqAOhxCMXLTeZUNfF6g= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Zheyu Ma , Greg Kroah-Hartman , Stefan Richter , Linus Torvalds , Sasha Levin Subject: [PATCH 5.11 129/152] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() Date: Mon, 5 Apr 2021 10:54:38 +0200 Message-Id: <20210405085038.425714650@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085034.233917714@linuxfoundation.org> References: <20210405085034.233917714@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Zheyu Ma [ Upstream commit 829933ef05a951c8ff140e814656d73e74915faf ] For each device, the nosy driver allocates a pcilynx structure. A use-after-free might happen in the following scenario: 1. Open nosy device for the first time and call ioctl with command NOSY_IOC_START, then a new client A will be malloced and added to doubly linked list. 2. Open nosy device for the second time and call ioctl with command NOSY_IOC_START, then a new client B will be malloced and added to doubly linked list. 3. Call ioctl with command NOSY_IOC_START for client A, then client A will be readded to the doubly linked list. Now the doubly linked list is messed up. 4. Close the first nosy device and nosy_release will be called. In nosy_release, client A will be unlinked and freed. 5. Close the second nosy device, and client A will be referenced, resulting in UAF. The root cause of this bug is that the element in the doubly linked list is reentered into the list. Fix this bug by adding a check before inserting a client. If a client is already in the linked list, don't insert it. The following KASAN report reveals it: BUG: KASAN: use-after-free in nosy_release+0x1ea/0x210 Write of size 8 at addr ffff888102ad7360 by task poc CPU: 3 PID: 337 Comm: poc Not tainted 5.12.0-rc5+ #6 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: nosy_release+0x1ea/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Allocated by task 337: nosy_open+0x154/0x4d0 misc_open+0x2ec/0x410 chrdev_open+0x20d/0x5a0 do_dentry_open+0x40f/0xe80 path_openat+0x1cf9/0x37b0 do_filp_open+0x16d/0x390 do_sys_openat2+0x11d/0x360 __x64_sys_open+0xfd/0x1a0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Freed by task 337: kfree+0x8f/0x210 nosy_release+0x158/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae The buggy address belongs to the object at ffff888102ad7300 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 96 bytes inside of 128-byte region [ffff888102ad7300, ffff888102ad7380) [ Modified to use 'list_empty()' inside proper lock - Linus ] Link: https://lore.kernel.org/lkml/1617433116-5930-1-git-send-email-zheyuma97@gmail.com/ Reported-and-tested-by: 马哲宇 (Zheyu Ma) Signed-off-by: Zheyu Ma Cc: Greg Kroah-Hartman Cc: Stefan Richter Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- drivers/firewire/nosy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 5fd6a60b6741..88ed971e32c0 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -346,6 +346,7 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct client *client = file->private_data; spinlock_t *client_list_lock = &client->lynx->client_list_lock; struct nosy_stats stats; + int ret; switch (cmd) { case NOSY_IOC_GET_STATS: @@ -360,11 +361,15 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case NOSY_IOC_START: + ret = -EBUSY; spin_lock_irq(client_list_lock); - list_add_tail(&client->link, &client->lynx->client_list); + if (list_empty(&client->link)) { + list_add_tail(&client->link, &client->lynx->client_list); + ret = 0; + } spin_unlock_irq(client_list_lock); - return 0; + return ret; case NOSY_IOC_STOP: spin_lock_irq(client_list_lock); -- 2.30.2