From patchwork Thu Jan 11 13:09:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Dryomov X-Patchwork-Id: 10157983 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 30A67602B3 for ; Thu, 11 Jan 2018 13:09:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0113F28792 for ; Thu, 11 Jan 2018 13:09:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3E9328809; Thu, 11 Jan 2018 13:09:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6EF8C2879C for ; Thu, 11 Jan 2018 13:09:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754503AbeAKNJW (ORCPT ); Thu, 11 Jan 2018 08:09:22 -0500 Received: from mail-wr0-f195.google.com ([209.85.128.195]:35739 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752317AbeAKNJV (ORCPT ); Thu, 11 Jan 2018 08:09:21 -0500 Received: by mail-wr0-f195.google.com with SMTP id n9so2117667wrg.2 for ; Thu, 11 Jan 2018 05:09:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=b7VgncXDPcgxGdlR3mt0wMx7d5k9L8sd8G4WeDP26YM=; b=YJRP3+980zPOn4/k4UFByGUvQXX2ZlLgCugbPA/GgiAryb2FncesThJ/E7x1BT074g 616tUmIaDKjzWf4Ryionm7stVqFR3qTcf018vwA5T98nepGI+dLtE6vQ4cspF3VBPFt1 HQAhcExeq57DGpayT/5BtuwpoIYeiscDDNvTo43Nd6bCh+b3n9mQtIGX4hsMpljknXYR yrVumI4CZ0lTOEpcf5xw2LPl7/XzuRO8pOdI7yLo0RAaWjpMl9Rn3XKrvI9HwVPc2b1l zneHhOcZg/Xm3pD+j2fukQYP8crt4MeJBw0s64rLYrh8NSCu+he7qqgapKwy2NUw+R3F xvAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=b7VgncXDPcgxGdlR3mt0wMx7d5k9L8sd8G4WeDP26YM=; b=BGiPFWr7agCw70MCkyKhBoSbuoXKuQBZqmTWaQVKeX0rO3vM447ml+7oC4yV8sdwuM IlXa+Uifx4jyCGFj//m9GSzd1Xa0kmdZ6KpeW1Q919BuyvqFOz0VXN3dM88psR7/a4Cw Jtg0j0cnxrR3YHsJYb/W6EaQwURZWVLw8/oj65Ta4l1Hkqkl1BtVEZD+DhwB4pMMHOou c3I+oSSXlp3Qsuv50OBuZZhYFrmwDgtbEbykXncrLAmdBMkwY6SJv+vMR/ZWropDvnLk WPfOj+zCbbUfWgnu33owTQCnVSHnzwTHJ3ZiPmM5qq8Zwj/hk8psF0s+7/9lboW4KtuE cKeQ== X-Gm-Message-State: AKGB3mJuXSArWHSd4eSlg7UWh5AafuYnyrhp5QSbXYAgFaYkpCRfu3tv r9tRRwHpnMX13ZtyS/UPP0S3jzgI X-Google-Smtp-Source: ACJfBotnTxZLR52HmC7VaGTnRIo7OAWmUSrizUqWw10TJBt22qM1Tk8gaUxTCG+WMOQUm4H7MBKSAg== X-Received: by 10.223.184.70 with SMTP id u6mr11953647wrf.212.1515676159968; Thu, 11 Jan 2018 05:09:19 -0800 (PST) Received: from orange.brq.redhat.com. (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id r3sm552960wmg.31.2018.01.11.05.09.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Jan 2018 05:09:19 -0800 (PST) From: Ilya Dryomov To: linux-block@vger.kernel.org Cc: Jens Axboe , Christoph Hellwig , Tejun Heo , David Disseldorp , Sagi Grimberg Subject: [PATCH v3 1/2] block: fail op_is_write() requests to read-only partitions Date: Thu, 11 Jan 2018 14:09:11 +0100 Message-Id: <1515676152-18476-2-git-send-email-idryomov@gmail.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1515676152-18476-1-git-send-email-idryomov@gmail.com> References: <1515676152-18476-1-git-send-email-idryomov@gmail.com> Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Regular block device writes go through blkdev_write_iter(), which does bdev_read_only(), while zeroout/discard/etc requests are never checked, both userspace- and kernel-triggered. Add a generic catch-all check to generic_make_request_checks() to actually enforce ioctl(BLKROSET) and set_disk_ro(), which is used by quite a few drivers for things like snapshots, read-only backing files/images, etc. Signed-off-by: Ilya Dryomov Reviewed-by: Sagi Grimberg --- block/blk-core.c | 56 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index f843ae4f858d..44a6dfe47ae1 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2062,6 +2062,21 @@ static inline bool should_fail_request(struct hd_struct *part, #endif /* CONFIG_FAIL_MAKE_REQUEST */ +static inline bool bio_check_ro(struct bio *bio, struct hd_struct *part) +{ + if (part->policy && op_is_write(bio_op(bio))) { + char b[BDEVNAME_SIZE]; + + printk(KERN_ERR + "generic_make_request: Trying to write " + "to read-only block-device %s (partno %d)\n", + bio_devname(bio, b), part->partno); + return true; + } + + return false; +} + /* * Remap block n of partition p to block n+start(p) of the disk. */ @@ -2070,27 +2085,28 @@ static inline int blk_partition_remap(struct bio *bio) struct hd_struct *p; int ret = 0; + rcu_read_lock(); + p = __disk_get_part(bio->bi_disk, bio->bi_partno); + if (unlikely(!p || should_fail_request(p, bio->bi_iter.bi_size) || + bio_check_ro(bio, p))) { + ret = -EIO; + goto out; + } + /* * Zone reset does not include bi_size so bio_sectors() is always 0. * Include a test for the reset op code and perform the remap if needed. */ - if (!bio->bi_partno || - (!bio_sectors(bio) && bio_op(bio) != REQ_OP_ZONE_RESET)) - return 0; + if (!bio_sectors(bio) && bio_op(bio) != REQ_OP_ZONE_RESET) + goto out; - rcu_read_lock(); - p = __disk_get_part(bio->bi_disk, bio->bi_partno); - if (likely(p && !should_fail_request(p, bio->bi_iter.bi_size))) { - bio->bi_iter.bi_sector += p->start_sect; - bio->bi_partno = 0; - trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p), - bio->bi_iter.bi_sector - p->start_sect); - } else { - printk("%s: fail for partition %d\n", __func__, bio->bi_partno); - ret = -EIO; - } - rcu_read_unlock(); + bio->bi_iter.bi_sector += p->start_sect; + bio->bi_partno = 0; + trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p), + bio->bi_iter.bi_sector - p->start_sect); +out: + rcu_read_unlock(); return ret; } @@ -2149,15 +2165,19 @@ generic_make_request_checks(struct bio *bio) * For a REQ_NOWAIT based request, return -EOPNOTSUPP * if queue is not a request based queue. */ - if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_rq_based(q)) goto not_supported; if (should_fail_request(&bio->bi_disk->part0, bio->bi_iter.bi_size)) goto end_io; - if (blk_partition_remap(bio)) - goto end_io; + if (!bio->bi_partno) { + if (unlikely(bio_check_ro(bio, &bio->bi_disk->part0))) + goto end_io; + } else { + if (blk_partition_remap(bio)) + goto end_io; + } if (bio_check_eod(bio, nr_sectors)) goto end_io;