Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp274284ybi; Wed, 29 May 2019 21:09:29 -0700 (PDT) X-Google-Smtp-Source: APXvYqz3voBd2U0sR6nJy8DAN5Vq3Tl032pVG7zHNf+tphQWG+HYRk+BvDXWGd/ClI5qMpuXAA32 X-Received: by 2002:a63:c02:: with SMTP id b2mr1871409pgl.5.1559189369386; Wed, 29 May 2019 21:09:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559189369; cv=none; d=google.com; s=arc-20160816; b=a+gcwxpq07P1Np4LDWCoWyv7qs1iF1NAEwDeTWRASxnYEM0+1puIn6saNDzMr0vbbW ycJvr8gD0OwuLHd85kVW4Rtc6R4rk8eCH16KlSXKtZvoPjcegOM4GYljHpUbCgvisc11 L/keeZPP48x6B4PZbjLQJSZPRNNShCp06hqilW92YbqdqcA6Oif3VV82J9Det6Mau20V a1F3qZpVRQ6uN7kFH9jizNfr5ZRegvGVizwcBj+6YwiwSx+0/NvHUsIqFwjZmbiqrGOk SiBB/Hr8FJyH1VOjvhp4ysEujT/m2RZVP2iAga7OMo4C6Q23zNkUpGucovpSkIDcAodF GlsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=zIFmq7JzB2ZgwhjblG+lfuqN78sUKJ4VB+ugeVn+/Ew=; b=lOlrk/ki388hk+bDLYhqp2wsIhDhliXq5SOEsJfhWLxrL9jroZdi3fc0cdFD4Tw5nI jQivovc3QVBZT0b10Girsf6bAwwVKArjxh2eaaOAbBA1LEIgnAMGdiXdypyDUlbOpCMw E6AnfZl63qms8cwszGVt48eA4xLmaDaEOWirW+ZYQ92FcBe5bh0Llsr4Vwc6e6GiyzY1 8lL883uj27xDAGLN4dBODy1af5/tWVh07BiH76HXMLEENBJZBnkerBcjCv8y7wscQnvl +DcqPbQqB21k6C95G8mWqWtbNbp2E0t/3poZp4VDkZXvrtPVbTwtfIftRZzNJEORdi5G j7VA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rHZ0wLxX; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z33si1888906pgk.516.2019.05.29.21.09.13; Wed, 29 May 2019 21:09:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=rHZ0wLxX; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726786AbfE3EGq (ORCPT + 99 others); Thu, 30 May 2019 00:06:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:47300 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731150AbfE3DRd (ORCPT ); Wed, 29 May 2019 23:17:33 -0400 Received: from localhost (ip67-88-213-2.z213-88-67.customer.algx.net [67.88.213.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 5684C24529; Thu, 30 May 2019 03:17:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559186252; bh=caT+T2CitUocF0Jn+HuJkazZXKeZpQsFfml6fIoB5wA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rHZ0wLxX7Xv5/r7wZzLPEUTUXCZjt7pAsSzAn30hsPkF84eCk3z10MF6QsgyNr6Vh +7inHSNGXj/BO3CJUJ3fzf9kHwtA/5sva778Ao0DHvHbTTh9aXYvJhtoD0Iuf3ED+N Syyw1LxrjrwHUgKCHFpgPNfAmqQeEimiE2vxHSI4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Al Viro , Bart Van Assche , Keith Busch , Jan Kara , Yufen Yu , Jens Axboe , Sasha Levin Subject: [PATCH 4.19 130/276] block: fix use-after-free on gendisk Date: Wed, 29 May 2019 20:04:48 -0700 Message-Id: <20190530030533.910471797@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190530030523.133519668@linuxfoundation.org> References: <20190530030523.133519668@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ Upstream commit 2c88e3c7ec32d7a40cc7c9b4a487cf90e4671bdd ] commit 2da78092dda "block: Fix dev_t minor allocation lifetime" specifically moved blk_free_devt(dev->devt) call to part_release() to avoid reallocating device number before the device is fully shutdown. However, it can cause use-after-free on gendisk in get_gendisk(). We use md device as example to show the race scenes: Process1 Worker Process2 md_free blkdev_open del_gendisk add delete_partition_work_fn() to wq __blkdev_get get_gendisk put_disk disk_release kfree(disk) find part from ext_devt_idr get_disk_and_module(disk) cause use after free delete_partition_work_fn put_device(part) part_release remove part from ext_devt_idr Before is removed from ext_devt_idr by delete_partition_work_fn(), we can find the devt and then access gendisk by hd_struct pointer. But, if we access the gendisk after it have been freed, it can cause in use-after-freeon gendisk in get_gendisk(). We fix this by adding a new helper blk_invalidate_devt() in delete_partition() and del_gendisk(). It replaces hd_struct pointer in idr with value 'NULL', and deletes the entry from idr in part_release() as we do now. Thanks to Jan Kara for providing the solution and more clear comments for the code. Fixes: 2da78092dda1 ("block: Fix dev_t minor allocation lifetime") Cc: Al Viro Reviewed-by: Bart Van Assche Reviewed-by: Keith Busch Reviewed-by: Jan Kara Suggested-by: Jan Kara Signed-off-by: Yufen Yu Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- block/genhd.c | 19 +++++++++++++++++++ block/partition-generic.c | 7 +++++++ include/linux/genhd.h | 1 + 3 files changed, 27 insertions(+) diff --git a/block/genhd.c b/block/genhd.c index be5bab20b2abf..2b2a936cf8480 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -518,6 +518,18 @@ void blk_free_devt(dev_t devt) } } +/** + * We invalidate devt by assigning NULL pointer for devt in idr. + */ +void blk_invalidate_devt(dev_t devt) +{ + if (MAJOR(devt) == BLOCK_EXT_MAJOR) { + spin_lock_bh(&ext_devt_lock); + idr_replace(&ext_devt_idr, NULL, blk_mangle_minor(MINOR(devt))); + spin_unlock_bh(&ext_devt_lock); + } +} + static char *bdevt_str(dev_t devt, char *buf) { if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) { @@ -769,6 +781,13 @@ void del_gendisk(struct gendisk *disk) if (!(disk->flags & GENHD_FL_HIDDEN)) blk_unregister_region(disk_devt(disk), disk->minors); + /* + * Remove gendisk pointer from idr so that it cannot be looked up + * while RCU period before freeing gendisk is running to prevent + * use-after-free issues. Note that the device number stays + * "in-use" until we really free the gendisk. + */ + blk_invalidate_devt(disk_devt(disk)); kobject_put(disk->part0.holder_dir); kobject_put(disk->slave_dir); diff --git a/block/partition-generic.c b/block/partition-generic.c index 5f8db5c5140f4..98d60a59b843c 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -289,6 +289,13 @@ void delete_partition(struct gendisk *disk, int partno) kobject_put(part->holder_dir); device_del(part_to_dev(part)); + /* + * Remove gendisk pointer from idr so that it cannot be looked up + * while RCU period before freeing gendisk is running to prevent + * use-after-free issues. Note that the device number stays + * "in-use" until we really free the gendisk. + */ + blk_invalidate_devt(part_devt(part)); hd_struct_kill(part); } diff --git a/include/linux/genhd.h b/include/linux/genhd.h index f767293b00e66..f13272d843320 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -596,6 +596,7 @@ struct unixware_disklabel { extern int blk_alloc_devt(struct hd_struct *part, dev_t *devt); extern void blk_free_devt(dev_t devt); +extern void blk_invalidate_devt(dev_t devt); extern dev_t blk_lookup_devt(const char *name, int partno); extern char *disk_name (struct gendisk *hd, int partno, char *buf); -- 2.20.1