Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3311623pxf; Mon, 5 Apr 2021 08:44:11 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyNDU92glhfrWDffh3zkvVAzPSfgHPBjyMOODDkLMl1y2z3oF6MM9BBiBLulU0bMsWe1JLi X-Received: by 2002:a6b:ea08:: with SMTP id m8mr19865174ioc.194.1617637451118; Mon, 05 Apr 2021 08:44:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617637451; cv=none; d=google.com; s=arc-20160816; b=MDj95zKMGWplsjm47Oks1DfdIWwmQmahsImq6+1Y4MFn7TzE1Vxcs/f81jhgAOaa6Q B77J3npxK4NeRumyIJ6Zc/rSbWJREiIBQ3FrqQ7ftjCIm9AsBQUUZodudcAmFHQGbPon 653/xJQZMU6xpCtnNMPAYEFGRpMdMMMFUBszmVR4mkkZNM6p4gly7RmXRrlR8N9c9QOR gFDQpYXEdRq8qoiUcb24dsUaVOueuIfv8phzLZyuC0m8O7VK0QmYJ+RqZx296IItnwt6 dOJl9NTo9yXniKdk4d69pBHR5yzhOWkaYV/7fQZ7giiggc9TdDqxXOtX0t9/GP3VAgJ7 jYQA== 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=i+xwVKszDEx7znMRPEtUyYkvlzeAJVhbykan4G5PbhQ=; b=F84GWUdRMJ3ms8tTFEL6teR2hjgdaGmClxfPg8G/SZRCy709CZei9ukI3U6UovbBnv SPPAmW0aGZSe/7uqjyY/ruFGC3j2NozEiLBb0H0egApascr/rsRJuxQNXgSWQsVN6nu1 YqC4MTeiN8ZjevIOiRYCy7qz0SXCJdqppqZuAyrBOxwEbGl/LVnAPwJ/nWowp/J1kr/F caZhhSeXbtQOFr9Wkw8Dx10kwl2TaUpuYT7ceku9AYulNFw+8Ns2LPt4j+Ie5j6Ktipw cVFxDov2OzsvrWHoobA2vlzEOdTc1b986YUGPYHfHFE/AyBC35fTqR3DZ8aQ/1p++B1K h0TQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=2k+TxyqT; 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 s4si8494630ilv.20.2021.04.05.08.43.57; Mon, 05 Apr 2021 08:44:11 -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=2k+TxyqT; 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 S238073AbhDEJGl (ORCPT + 99 others); Mon, 5 Apr 2021 05:06:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:48278 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238501AbhDEJFC (ORCPT ); Mon, 5 Apr 2021 05:05:02 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 700826139D; Mon, 5 Apr 2021 09:04:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617613495; bh=n+xJmCDSVXvBQULx+GnFO8Z5eb7mV3X7wFPrmp1fb1M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=2k+TxyqT4UsFoisVLSRjgFtINA8R3ppZi/jQsBHs4f2C9PHrLzQpMt9IlfRY+ca2Y /3yRqz42xe4vSfdbfsVb9JfH3iQzMHq8O4VDejdqfyyScZKKsTPbeOHRX3dhdHdOHo cukEXWFy0UMYmY6rB2Jj2LgiqbMrc9nicYOOuVJw= 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.4 59/74] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() Date: Mon, 5 Apr 2021 10:54:23 +0200 Message-Id: <20210405085026.641053879@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085024.703004126@linuxfoundation.org> References: <20210405085024.703004126@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 0cc746673677..9ee747a85ee4 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