Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp876577pxb; Wed, 1 Sep 2021 11:53:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzotQP45M4qtNOwcMBi2NVB2fY5votka2jypa4SzG6TsZFvzECk5Q3QFMx69Xjc382f2sEe X-Received: by 2002:aa7:c353:: with SMTP id j19mr1132751edr.48.1630522428541; Wed, 01 Sep 2021 11:53:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630522428; cv=none; d=google.com; s=arc-20160816; b=eydf3XnHHWxnLL3IjPos0xB0YVMsXhbNcKLQzudDh6K5spe691JJIEZ+6+O0HGPM1p LI57z6bxCZMsZfbHnfuBpAPZEKAfk8BuD0VS6aAly+zqOxZ4/MoeUWItbbWub8cwASFG rjcbJ/16l75Mj0TBB9mSJOJnmakVQ9b45bfvG2zwvkgWA1kHVoBK3XrZYmpfawopEIDM zCXIY9yvjWVhgNkuoJrBQCAi0sCO5ZCts/AZf9fqZe/MRNCGmmiKyzxcVyRiLQYmwcER 8qy+Ku1ogS5WMF0hhzcbYRCUo4WyPaHvcPvagTrSfUjVFKJyUZKdw1thYxqYRFDJuo6Z dTPg== 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=cqYOFzsXxPfOqMTbqob4VONz5Od2FJlDlhgARQhOAcI=; b=ZwsKE/GTy1/uWDt/txYf/UbwhDvA9tMUMNAd+VEaXg1LVXuYA5MOLd7FJHPkhzCVfb zsBuI+MSgYtvLWkicTWkpqwJwyoq4Fox9eiGp7VFOscpSL9IS0WHKfDjSHQjHtGxOR4G 4vqjVjIcRE2qxuvrhoRmTZcwAtWeTxuqPuVIrNyL/3PAA12GsAWjfghcTZXos6Mxus9e mZCkHj1G81immOIMEwRaZ8hseCCoisWhUrsWAJdTcZIYAiLkPNBBy3wJjG0KdDfMCz3E KcAieqvMBOSxXI4yOBzvURrmBxsoEcmRZqQiKSY+RQ5iDJ3lwtcLOIZQOo5eBwGH6Sq6 wiWw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=li7cJI1G; 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 r24si335511edp.67.2021.09.01.11.53.25; Wed, 01 Sep 2021 11:53:48 -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=li7cJI1G; 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 S1343658AbhIAMgI (ORCPT + 99 others); Wed, 1 Sep 2021 08:36:08 -0400 Received: from mail.kernel.org ([198.145.29.99]:34434 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343695AbhIAMeR (ORCPT ); Wed, 1 Sep 2021 08:34:17 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id E41EC60232; Wed, 1 Sep 2021 12:32:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1630499552; bh=xugerIigWI5/7QjSImQOZqYfeI7w9gSezyYgcWWVdIw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=li7cJI1GdrYozUytQGlefjPEzi3V66dpYlA3Uu0SA48e3XZ8nO2+w1sivp7+siMt8 dwZ1H9+IQPwEhbaJXWvUZT6JIZnmZv7xjQZQsbQs7QjMRvBlKcXtja7exCEhGZlhtu RXhpW4p0yb4vTojdBMn4IfpiDKqmgk6Rqv2Z6xmk= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, butt3rflyh4ck , Anand Jain , Qu Wenruo , David Sterba Subject: [PATCH 5.4 44/48] btrfs: fix NULL pointer dereference when deleting device by invalid id Date: Wed, 1 Sep 2021 14:28:34 +0200 Message-Id: <20210901122254.832348113@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210901122253.388326997@linuxfoundation.org> References: <20210901122253.388326997@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: Qu Wenruo commit e4571b8c5e9ffa1e85c0c671995bd4dcc5c75091 upstream. [BUG] It's easy to trigger NULL pointer dereference, just by removing a non-existing device id: # mkfs.btrfs -f -m single -d single /dev/test/scratch1 \ /dev/test/scratch2 # mount /dev/test/scratch1 /mnt/btrfs # btrfs device remove 3 /mnt/btrfs Then we have the following kernel NULL pointer dereference: BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 9 PID: 649 Comm: btrfs Not tainted 5.14.0-rc3-custom+ #35 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:btrfs_rm_device+0x4de/0x6b0 [btrfs] btrfs_ioctl+0x18bb/0x3190 [btrfs] ? lock_is_held_type+0xa5/0x120 ? find_held_lock.constprop.0+0x2b/0x80 ? do_user_addr_fault+0x201/0x6a0 ? lock_release+0xd2/0x2d0 ? __x64_sys_ioctl+0x83/0xb0 __x64_sys_ioctl+0x83/0xb0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x44/0xae [CAUSE] Commit a27a94c2b0c7 ("btrfs: Make btrfs_find_device_by_devspec return btrfs_device directly") moves the "missing" device path check into btrfs_rm_device(). But btrfs_rm_device() itself can have case where it only receives @devid, with NULL as @device_path. In that case, calling strcmp() on NULL will trigger the NULL pointer dereference. Before that commit, we handle the "missing" case inside btrfs_find_device_by_devspec(), which will not check @device_path at all if @devid is provided, thus no way to trigger the bug. [FIX] Before calling strcmp(), also make sure @device_path is not NULL. Fixes: a27a94c2b0c7 ("btrfs: Make btrfs_find_device_by_devspec return btrfs_device directly") CC: stable@vger.kernel.org # 5.4+ Reported-by: butt3rflyh4ck Reviewed-by: Anand Jain Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/volumes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2168,7 +2168,7 @@ int btrfs_rm_device(struct btrfs_fs_info if (IS_ERR(device)) { if (PTR_ERR(device) == -ENOENT && - strcmp(device_path, "missing") == 0) + device_path && strcmp(device_path, "missing") == 0) ret = BTRFS_ERROR_DEV_MISSING_NOT_FOUND; else ret = PTR_ERR(device);