From patchwork Mon Jun 12 07:41:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingbo Xu X-Patchwork-Id: 106289 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp2418735vqr; Mon, 12 Jun 2023 00:52:42 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6HJMV9KF2vPxyPkrB7ALnWaKJUHjKPpKR3BN0tErzjywCq/2vc54If4GBHlsvWDLOO3D/Q X-Received: by 2002:a17:902:e802:b0:1b3:de47:fafc with SMTP id u2-20020a170902e80200b001b3de47fafcmr18850plg.7.1686556361742; Mon, 12 Jun 2023 00:52:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686556361; cv=none; d=google.com; s=arc-20160816; b=Kzq0EuJ7qA1H5F80wY5P6QYS9wOCUuKvI8VlOZG3yCipv5XKfd/7+yyYTHmHgyFS68 KzDPMQEx92L+MEtUeJvOH6MwiKCYXRayFli/E7z/WuXanvcFkRADdAZH9j13t41UZW8Z UkaxO8+VrcLosgqWlSKMF16M+bEVo6COGixR6qOJ9qAS7bpR2eSvZB/1sWylIpOW30pM HD1Xv9s7pkAJrp3dh9p4a+Gnl9qKMa4G1J5RnW10PBVzDYlj5/ReDxfAtPEe16foLg0o mxaoByoqyGZrsV4KBWM3imECFWODTzzRNHmJdtz4F6InkqIfYEFRNPzA8u2xcMg54rG3 2ojg== 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 :message-id:date:subject:cc:to:from; bh=nfjkx+Wme2/SeQberzR1GYn7YVdZtKcPw7GEuy4bxok=; b=caLjcu3QJbNE21IroxOXhOsCCD4P/5c7hVusOEnMOdPs/v8Z0h6oasYGp+4CVjd8L5 MUggWSCFK4PdOWq/l/nlTFcV2mzlPLEyfpWjmmiORGSfP6m4BgmNDmdUxXkRFoKrsfEu r7jcoDdbOTbPAS9cXGkQy2HukMIx8S7VRq8Wa86VG4lqhwnauWcE3nzJzhnhNtdDem4f E/bkOqG/ThBLCXLMIrdHalrSpayoPy/FT+lNzDZEOfhlGPuL5Pg27XRUuQeHP7c/ZNir wlWQmbHdernlcq8WG3N6dUSymxi296ee3EPnWFnhl9TcomeA4ZT4kQi/Dx1EvyPV2BzA 6WwA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id e8-20020a170902ef4800b001ab18eacb8csi6628846plx.526.2023.06.12.00.52.29; Mon, 12 Jun 2023 00:52:41 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234786AbjFLHnP (ORCPT + 99 others); Mon, 12 Jun 2023 03:43:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234982AbjFLHnM (ORCPT ); Mon, 12 Jun 2023 03:43:12 -0400 Received: from out30-111.freemail.mail.aliyun.com (out30-111.freemail.mail.aliyun.com [115.124.30.111]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 564AA170B; Mon, 12 Jun 2023 00:42:37 -0700 (PDT) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R201e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018046059;MF=jefflexu@linux.alibaba.com;NM=1;PH=DS;RN=7;SR=0;TI=SMTPD_---0Vku1XZA_1686555663; Received: from localhost(mailfrom:jefflexu@linux.alibaba.com fp:SMTPD_---0Vku1XZA_1686555663) by smtp.aliyun-inc.com; Mon, 12 Jun 2023 15:41:04 +0800 From: Jingbo Xu To: axboe@kernel.dk, hch@lst.de, linux-block@vger.kernel.org Cc: linux-kernel@vger.kernel.org, tianjia.zhang@linux.alibaba.com, xiang@kernel.org, casey@schaufler-ca.com Subject: [PATCH v2] block: fine-granular CAP_SYS_ADMIN for Persistent Reservation ioctl Date: Mon, 12 Jun 2023 15:41:03 +0800 Message-Id: <20230612074103.4866-1-jefflexu@linux.alibaba.com> X-Mailer: git-send-email 2.19.1.6.gb485710b MIME-Version: 1.0 X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,UNPARSEABLE_RELAY,USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1768482523323885956?= X-GMAIL-MSGID: =?utf-8?q?1768482523323885956?= Allow of unprivileged Persistent Reservation (PR) operations on devices if the write permission check on the device node has passed. Besides, refuse the unprivileged PR operations on partitions as reservations on partitions doesn't make sense. Signed-off-by: Jingbo Xu --- changes since RFC: - only allow unprivileged reservations if the file descriptor is open for write (Christoph Hellwig) - refuse the unprivileged reservations on partitions (Christoph Hellwig) (maybe this checking shall also be done when CAP_SYS_ADMIN is set?) RFC: https://lore.kernel.org/all/20230609102122.118800-1-jefflexu@linux.alibaba.com/ --- block/ioctl.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index 9c5f637ff153..420dc4701f9c 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -254,13 +254,29 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, fmode_t mode, EXPORT_SYMBOL(blkdev_compat_ptr_ioctl); #endif -static int blkdev_pr_register(struct block_device *bdev, +static bool blkdev_pr_allowed(struct block_device *bdev, fmode_t mode) +{ + if (capable(CAP_SYS_ADMIN)) + return true; + + /* no sense to make reservations for partitions */ + if (bdev_is_partition(bdev)) + return false; + + /* + * Only allow unprivileged reservations if the file descriptor is open + * for writing. + */ + return mode & FMODE_WRITE; +} + +static int blkdev_pr_register(struct block_device *bdev, fmode_t mode, struct pr_registration __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_registration reg; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_register) return -EOPNOTSUPP; @@ -272,13 +288,13 @@ static int blkdev_pr_register(struct block_device *bdev, return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags); } -static int blkdev_pr_reserve(struct block_device *bdev, +static int blkdev_pr_reserve(struct block_device *bdev, fmode_t mode, struct pr_reservation __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_reservation rsv; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_reserve) return -EOPNOTSUPP; @@ -290,13 +306,13 @@ static int blkdev_pr_reserve(struct block_device *bdev, return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags); } -static int blkdev_pr_release(struct block_device *bdev, +static int blkdev_pr_release(struct block_device *bdev, fmode_t mode, struct pr_reservation __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_reservation rsv; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_release) return -EOPNOTSUPP; @@ -308,13 +324,13 @@ static int blkdev_pr_release(struct block_device *bdev, return ops->pr_release(bdev, rsv.key, rsv.type); } -static int blkdev_pr_preempt(struct block_device *bdev, +static int blkdev_pr_preempt(struct block_device *bdev, fmode_t mode, struct pr_preempt __user *arg, bool abort) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_preempt p; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_preempt) return -EOPNOTSUPP; @@ -326,13 +342,13 @@ static int blkdev_pr_preempt(struct block_device *bdev, return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort); } -static int blkdev_pr_clear(struct block_device *bdev, +static int blkdev_pr_clear(struct block_device *bdev, fmode_t mode, struct pr_clear __user *arg) { const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; struct pr_clear c; - if (!capable(CAP_SYS_ADMIN)) + if (!blkdev_pr_allowed(bdev, mode)) return -EPERM; if (!ops || !ops->pr_clear) return -EOPNOTSUPP; @@ -534,17 +550,17 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode, case BLKTRACETEARDOWN: return blk_trace_ioctl(bdev, cmd, argp); case IOC_PR_REGISTER: - return blkdev_pr_register(bdev, argp); + return blkdev_pr_register(bdev, mode, argp); case IOC_PR_RESERVE: - return blkdev_pr_reserve(bdev, argp); + return blkdev_pr_reserve(bdev, mode, argp); case IOC_PR_RELEASE: - return blkdev_pr_release(bdev, argp); + return blkdev_pr_release(bdev, mode, argp); case IOC_PR_PREEMPT: - return blkdev_pr_preempt(bdev, argp, false); + return blkdev_pr_preempt(bdev, mode, argp, false); case IOC_PR_PREEMPT_ABORT: - return blkdev_pr_preempt(bdev, argp, true); + return blkdev_pr_preempt(bdev, mode, argp, true); case IOC_PR_CLEAR: - return blkdev_pr_clear(bdev, argp); + return blkdev_pr_clear(bdev, mode, argp); default: return -ENOIOCTLCMD; }