Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3160049pxf; Mon, 5 Apr 2021 05:01:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw4LYfHGOAFym7VVnC/IhIA8dNEleVcSY08oNxZRMG4eR8/d5KrSiWq+8vtoxhu6REtGuDS X-Received: by 2002:a02:caa9:: with SMTP id e9mr23360256jap.59.1617624114627; Mon, 05 Apr 2021 05:01:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617624114; cv=none; d=google.com; s=arc-20160816; b=loJauhTnJB283Z1E6aa+ljuo/xZAzRwqzPGaKiwY7GIS+l5EiAABG8iKOezT2lyLw9 ZO9+fh6ZPtnRQZldL2rCaprDjUCkWAAuOLs/H+YeIsW6FFehRg0EgLRST1CNHe7T89fB q/nfspmUxKa5VRx1BAo8Wv/2Km4dYUQo6tSrFukxmSdA1DcNn6Htuj26aCHDCV57g3HZ E5CoeZMMJYS5NHpyvrSfbRIU0i6zENx1elc2+VrS4ikuuFdB9xcaGOQSrwlejiIuOy9e rfJ2BCpZZzoEbFvLXnZEItbOAlxggeTt1eb2bKaq8a5IU3zVJrhmZUj6YgMEbFcpZlHp 54tg== 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=Gj6KgCfeNI4fZlI1QdDaGiaLymRi30Vrkc0wlKC3qvo=; b=kdtYQ4tGtYZQzK8Y0x9HWfSZKF7ZpfLtIbyO9PFn8+M8bx+3YiYejQoMQZpplCmQbV HrfhDhXcN7Qkab9cJAOPAdKwwhobWhxG5+LjoUteq6Iw6rrhk7nUSZpab4GxEdq4bMEE gF8c9MW0dPh6xjRrpwyG7Jo/S2cnr+RhH/QoKjwS8XUMzOH/EAg+lRA5im3xWnaisqG4 QAJmzpR8a5l/nSWGST62rHfg1zeWJwFZsRoNo2m58m2EShhmZAgW/pvLHFps7nUchz/V LNCnEBI0+sN5NKqJQc8MlP4VmYI5f3nKWvGcckIBnMokAnXJWoLfaCvvtW2H43yJZAwF aaFA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=mfoKWuRp; 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 q11si7434950ilt.93.2021.04.05.05.01.30; Mon, 05 Apr 2021 05:01:54 -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=mfoKWuRp; 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 S237097AbhDEI75 (ORCPT + 99 others); Mon, 5 Apr 2021 04:59:57 -0400 Received: from mail.kernel.org ([198.145.29.99]:40112 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236431AbhDEI7U (ORCPT ); Mon, 5 Apr 2021 04:59:20 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 68E996138A; Mon, 5 Apr 2021 08:59:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617613154; bh=teHUG3InJy7OYJvmr2kg+wS5qfOI8ycdVjxF0yfQmvs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mfoKWuRpW2jR6ZMpbs49TwvwkbI19/OkUhtSVhMWITU+KUJ1f0vZT/2CEEh4YSXzH Pq7Ry+o8Z2M/+DtKoaOnwLhTTwOkERxGFOKrNVnXTMswXkGPurxOzduqRKFeOO/zo0 Mcw74RR0KfyvAoeZSKogpbsbbk4M+5uWHmv6H4wI= 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 4.14 40/52] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() Date: Mon, 5 Apr 2021 10:54:06 +0200 Message-Id: <20210405085023.287968422@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085021.996963957@linuxfoundation.org> References: <20210405085021.996963957@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 180f0a96528c..646dca0a8d73 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -359,6 +359,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: @@ -373,11 +374,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