Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3262198pxf; Mon, 5 Apr 2021 07:32:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzwf5zx8BpMupSVcWTT2Z4hGRrm8L3uYM1lc31mChNAEDw8r9d05mAAbCWavQe52Olbj24m X-Received: by 2002:a17:906:1697:: with SMTP id s23mr4884736ejd.156.1617633143018; Mon, 05 Apr 2021 07:32:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617633143; cv=none; d=google.com; s=arc-20160816; b=rH4duYyi2ZM9/Dwv/tuJFmi5jCsq0rSRr1qfAb2EkkqX1TM0Vm44d+IqNW5G/aAn4/ qmoTmlt73m4rjqT+o36rdxIdnC/bQ/j6Tp5KGMqLvs3vgm2OGPvx4xznGWF5nww2KxBr a5YOPrykwuTMSmOdrckhXihxMHNccAMtdsQiWwIATcJDNRA9pAIoLWeX2AY6lN+3xogr ZmbdtV7yXki0HI7ckiGmv45OQgfb9Wq3ksYBsFzJZbaAJ0FiP5WWUC8sJlkMPFk/S3du QrTbCLSlmnVV4seYCm0mcwm3LD2VJLxPm3IYlJ8ZP6CX1ZzoqexpzZTSlZiizzo21QMz 0FEw== 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=xdMYHiu38fSmKdcKpfWUN7z/c2DLGAQRe0sIyutz/e0=; b=ISaFaIpDylw9/hwJjMU2DEsPGhgeNKakjhAHzA2SqdWMHr2ORRbIyLYBTKKIPOfW/j 4NoVOfW8V/Cs5gneqjb24wzKYUEEX8tkdAKgyXy63dPPUKEqEw6lGaGQNOgtlID7Re+7 pUsai7axOeBfNCdvUu5cFNOgGtuVAhaqu+B7ga/mYcqNIxRuzgdV3bvOpiYWgjURjaKR CNuZj4WeHpEdoHxWYVjDNvV58boOvLK8/ep+0B4bsAMHgNPmp4bCLgrd46M1tS/q9q21 Iwqs7CsuohUsoiiKhK01qJEuWAg2xyUqsiqcL1wdRJWoJaV75f9zigLb38H57/6Ge/OS 4EgA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=bFYnVyyG; 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 bo20si4974994edb.312.2021.04.05.07.31.59; Mon, 05 Apr 2021 07:32:23 -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=bFYnVyyG; 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 S237710AbhDEJDk (ORCPT + 99 others); Mon, 5 Apr 2021 05:03:40 -0400 Received: from mail.kernel.org ([198.145.29.99]:43412 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234181AbhDEJCI (ORCPT ); Mon, 5 Apr 2021 05:02:08 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 07C3F613A9; Mon, 5 Apr 2021 09:01:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1617613297; bh=ToeGCkHKi2vSOjcD0006RoYI7g9oDmEl5Hc9CN4HfC8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bFYnVyyG0otxfjkUYxwEUujydyHpJKqx9KivtQecD80zn7u8Z1evTeWjKNb3J9RbN 82J7QA6OOKDXfwD63fSp3aAcLeM1R0G39g2cG0yOM4ATMSLX3S8dHlxogveUpm+aMQ yklAdYhEClFcY04lUROn8aQIPECuh8mAxrya9IkA= 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.19 42/56] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() Date: Mon, 5 Apr 2021 10:54:13 +0200 Message-Id: <20210405085023.876335246@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210405085022.562176619@linuxfoundation.org> References: <20210405085022.562176619@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 a128dd1126ae..ac85e03e88e1 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