Received: by 2002:a5d:9c59:0:0:0:0:0 with SMTP id 25csp2834937iof; Wed, 8 Jun 2022 13:05:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyHdij65C8pHfW/MiZBZOf2eyo+2LLgslTZ8Edb3YZZnMO7W211oqka4VCE9t/Lus4p/cIJ X-Received: by 2002:a17:90b:1d90:b0:1e8:5a98:d591 with SMTP id pf16-20020a17090b1d9000b001e85a98d591mr922459pjb.126.1654718736248; Wed, 08 Jun 2022 13:05:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654718736; cv=none; d=google.com; s=arc-20160816; b=UrmaUQEFpaBUUIQkkjlhd2dh16lYv4Xmmmgwunxrfrc4PF6J9+OQwXhDSlUyPTxOkQ InF3y8ogU/frRsHHHybUkWGpM4Q70veCDU09fFNZnVqt6Z4TTJWS34EII8/5OfI3QWow iC+VhF13C8qfmUvTkK1SpdS+iBYsIhVRylVNw9X4NaSvd4Em8xVaP+OeJSB74EclEBZ9 ARwnM020Kr9Xmwfz9CTkOuYJneqj9G87T0fzUn6YiiQBJEoh8Q1Pm6Pt0LCYdUb3Xf0l kU8B3IbeKP0JBmn7E/z0fY9Tuqs357GGbDp8p/aZeAWQjdR+Oj4KHMjGSvvLTHlzgFbE iLfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature:dkim-filter; bh=oxcl4VWDjkQJJLUJyWVlObluHCw+WnAyBzJSnSbo5Wo=; b=FmHq6iX1c98TAy7cgoskDTkXullI9M5dBtdHkCYzwdXxHuUp0TBkj69WuOMH5xLOWm sJ+p0KkjalL7EVaczih696i0jA/VucvojIx09Ppc2jqcfHngVlpR+57Sk4UX4aRRGy7s SQ/R4i92WfpT5GxeXxP7WvU4YWDQTDQqpP8gOOU4yinCrzMM93DtjegDmq5jNMpAgR31 Dk5aCrF1Wd0LXFeqDmeeOU5qfjURF47aRkyxI6rk7A7wUB4wYjnbXkDBMga8f4Bg0C1k 17vo47UQaNegv7CZAF32/OqWjdCozm//8JqUQsf40T/NjLPHUlP+GmaMZj3zopPvJ9cb A12A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=lJDMB5uQ; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j9-20020a056a00130900b004fa3a8dff9dsi29011425pfu.84.2022.06.08.13.05.24; Wed, 08 Jun 2022 13:05:36 -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; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=lJDMB5uQ; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234831AbiFHTCN (ORCPT + 99 others); Wed, 8 Jun 2022 15:02:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234120AbiFHTBs (ORCPT ); Wed, 8 Jun 2022 15:01:48 -0400 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B35073AA5A; Wed, 8 Jun 2022 12:01:46 -0700 (PDT) Received: from linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net (linux.microsoft.com [13.77.154.182]) by linux.microsoft.com (Postfix) with ESMTPSA id D439320BE676; Wed, 8 Jun 2022 12:01:44 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com D439320BE676 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1654714904; bh=oxcl4VWDjkQJJLUJyWVlObluHCw+WnAyBzJSnSbo5Wo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lJDMB5uQ6vPGJXTjSq9o9osNKOSh8UJPSZQoLi2AkXYWEmNtTIhtJ9oB02s+3XFno C+hAPTo2p2AUdKXJCsKSQh141aDytqF+vPzToYg33NXO9VWsWcE08CuELX+6GLrBHx 9ALvKVoYb19eg4cntYIazz/KqAcgHhORTmHPXynE= From: Deven Bowers To: corbet@lwn.net, zohar@linux.ibm.com, jmorris@namei.org, serge@hallyn.com, tytso@mit.edu, ebiggers@kernel.org, axboe@kernel.dk, agk@redhat.com, snitzer@kernel.org, eparis@redhat.com, paul@paul-moore.com Cc: linux-doc@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-block@vger.kernel.org, dm-devel@redhat.com, linux-audit@redhat.com, roberto.sassu@huawei.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH v8 10/17] block|security: add LSM blob to block_device Date: Wed, 8 Jun 2022 12:01:22 -0700 Message-Id: <1654714889-26728-11-git-send-email-deven.desai@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1654714889-26728-1-git-send-email-deven.desai@linux.microsoft.com> References: <1654714889-26728-1-git-send-email-deven.desai@linux.microsoft.com> X-Spam-Status: No, score=-19.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_MED, SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL, 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 block_device structures can have valuable security properties, based on how they are created, and what subsystem manages them. By adding LSM storage to this structure, this data can be accessed at the LSM layer. Signed-off-by: Deven Bowers --- v2: + No Changes v3: + Minor style changes from checkpatch --strict v4: + No Changes v5: + Allow multiple callers to call security_bdev_setsecurity v6: + Simplify security_bdev_setsecurity break condition v7: + Squash all dm-verity related patches to two patches, the additions to dm-verity/fs, and the consumption of the additions. v8: + Split dm-verity related patches squashed in v7 to 3 commits based on topic: + New LSM hook + Consumption of hook outside LSM + Consumption of hook inside LSM. + change return of security_bdev_alloc / security_bdev_setsecurity to LSM_RET_DEFAULT instead of 0. + Change return code to -EOPNOTSUPP, bring inline with other setsecurity hooks. --- block/bdev.c | 7 ++++ include/linux/blk_types.h | 1 + include/linux/lsm_hook_defs.h | 5 +++ include/linux/lsm_hooks.h | 12 ++++++ include/linux/security.h | 22 +++++++++++ security/security.c | 70 +++++++++++++++++++++++++++++++++++ 6 files changed, 117 insertions(+) diff --git a/block/bdev.c b/block/bdev.c index 5fe06c1f2def..e7ef2c7a22c9 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include "../fs/internal.h" @@ -397,6 +398,11 @@ static struct inode *bdev_alloc_inode(struct super_block *sb) if (!ei) return NULL; memset(&ei->bdev, 0, sizeof(ei->bdev)); + + if (unlikely(security_bdev_alloc(&ei->bdev))) { + kmem_cache_free(bdev_cachep, ei); + return NULL; + } return &ei->vfs_inode; } @@ -406,6 +412,7 @@ static void bdev_free_inode(struct inode *inode) free_percpu(bdev->bd_stats); kfree(bdev->bd_meta_info); + security_bdev_free(bdev); if (!bdev_is_partition(bdev)) { if (bdev->bd_disk && bdev->bd_disk->bdi) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index a24d4078fb21..a014ffa14b2d 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -68,6 +68,7 @@ struct block_device { #ifdef CONFIG_FAIL_MAKE_REQUEST bool bd_make_it_fail; #endif + void *security; } __randomize_layout; #define bdev_whole(_bdev) \ diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index eafa1d2489fd..3449c004bd84 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -407,3 +407,8 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) LSM_HOOK(int, 0, uring_override_creds, const struct cred *new) LSM_HOOK(int, 0, uring_sqpoll, void) #endif /* CONFIG_IO_URING */ + +LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev) +LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) +LSM_HOOK(int, 0, bdev_setsecurity, struct block_device *bdev, const char *name, + const void *value, size_t size) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 91c8146649f5..9f011d705ea8 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1550,6 +1550,17 @@ * * @what: kernel feature being accessed * + * @bdev_alloc_security: + * Initialize the security field inside a block_device structure. + * + * @bdev_free_security: + * Cleanup the security information stored inside a block_device structure. + * + * @bdev_setsecurity: + * Set a security property associated with @name for @bdev with + * value @value. @size indicates the size of @value in bytes. + * If a @name is not implemented, return -EOPNOTSUPP. + * * Security hooks for perf events * * @perf_event_open: @@ -1610,6 +1621,7 @@ struct lsm_blob_sizes { int lbs_ipc; int lbs_msg_msg; int lbs_task; + int lbs_bdev; }; /* diff --git a/include/linux/security.h b/include/linux/security.h index 7fc4e9f49f54..30b663de301f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -473,6 +473,11 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); +int security_bdev_alloc(struct block_device *bdev); +void security_bdev_free(struct block_device *bdev); +int security_bdev_setsecurity(struct block_device *bdev, + const char *name, const void *value, + size_t size); #else /* CONFIG_SECURITY */ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) @@ -1349,6 +1354,23 @@ static inline int security_locked_down(enum lockdown_reason what) { return 0; } + +static inline int security_bdev_alloc(struct block_device *bdev) +{ + return 0; +} + +static inline void security_bdev_free(struct block_device *bdev) +{ +} + +static inline int security_bdev_setsecurity(struct block_device *bdev, + const char *name, + const void *value, size_t size) +{ + return 0; +} + #endif /* CONFIG_SECURITY */ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) diff --git a/security/security.c b/security/security.c index 188b8f782220..59ec336788e8 100644 --- a/security/security.c +++ b/security/security.c @@ -29,6 +29,7 @@ #include #include #include +#include #define MAX_LSM_EVM_XATTR 2 @@ -208,6 +209,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock); lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); + lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev); } /* Prepare LSM for initialization. */ @@ -344,6 +346,7 @@ static void __init ordered_lsm_init(void) init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); init_debug("task blob size = %d\n", blob_sizes.lbs_task); + init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); /* * Create any kmem_caches needed for blobs @@ -660,6 +663,28 @@ static int lsm_msg_msg_alloc(struct msg_msg *mp) return 0; } +/** + * lsm_bdev_alloc - allocate a composite block_device blob + * @bdev: the block_device that needs a blob + * + * Allocate the block_device blob for all the modules + * + * Returns 0, or -ENOMEM if memory can't be allocated. + */ +static int lsm_bdev_alloc(struct block_device *bdev) +{ + if (blob_sizes.lbs_bdev == 0) { + bdev->security = NULL; + return 0; + } + + bdev->security = kzalloc(blob_sizes.lbs_bdev, GFP_KERNEL); + if (!bdev->security) + return -ENOMEM; + + return 0; +} + /** * lsm_early_task - during initialization allocate a composite task blob * @task: the task that needs a blob @@ -2617,6 +2642,51 @@ int security_locked_down(enum lockdown_reason what) } EXPORT_SYMBOL(security_locked_down); +int security_bdev_alloc(struct block_device *bdev) +{ + int rc = 0; + + rc = lsm_bdev_alloc(bdev); + if (unlikely(rc)) + return rc; + + rc = call_int_hook(bdev_alloc_security, 0, bdev); + if (unlikely(rc)) + security_bdev_free(bdev); + + return LSM_RET_DEFAULT(bdev_alloc_security); +} +EXPORT_SYMBOL(security_bdev_alloc); + +void security_bdev_free(struct block_device *bdev) +{ + if (!bdev->security) + return; + + call_void_hook(bdev_free_security, bdev); + + kfree(bdev->security); + bdev->security = NULL; +} +EXPORT_SYMBOL(security_bdev_free); + +int security_bdev_setsecurity(struct block_device *bdev, + const char *name, const void *value, + size_t size) +{ + int rc = 0; + struct security_hook_list *p; + + hlist_for_each_entry(p, &security_hook_heads.bdev_setsecurity, list) { + rc = p->hook.bdev_setsecurity(bdev, name, value, size); + if (rc && rc != -EOPNOTSUPP) + return rc; + } + + return LSM_RET_DEFAULT(bdev_setsecurity); +} +EXPORT_SYMBOL(security_bdev_setsecurity); + #ifdef CONFIG_PERF_EVENTS int security_perf_event_open(struct perf_event_attr *attr, int type) { -- 2.25.1