Message ID | 20231107134012.682009-23-roberto.sassu@huaweicloud.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:aa0b:0:b0:403:3b70:6f57 with SMTP id k11csp245497vqo; Tue, 7 Nov 2023 05:51:40 -0800 (PST) X-Google-Smtp-Source: AGHT+IHPPoqdm+vRzY3oW4b+0+9+OG+XmMwkm1Z0Pro+AwgnyPGOJrNA6qLsX5lgmaiEiEnRbghx X-Received: by 2002:a05:6e02:1c07:b0:357:f730:cc4c with SMTP id l7-20020a056e021c0700b00357f730cc4cmr3122252ilh.6.1699365100191; Tue, 07 Nov 2023 05:51:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1699365100; cv=none; d=google.com; s=arc-20160816; b=d5Lr6xEP4KMzF5QrtebRnSktoMI2CwFrmjVUnrTk6n1sp148u8gI7MWHm7krSC+rp9 GiceydNzCc6m4ZPHD/RwCJR2Cui/qc4jmcj/3GoeB2VUjklJPUtzE+fR5lTaaA7XoozD QLH4ioooCNnRRDjEtuJFxsF7r5flAlfGa3DuGF1ThaIXPZvXfVPXCK9ld/eGMNzag83r esYF4Av34M+hn4tr3QqU55B6t98iu084m1iLnHeiX1GSoYvAwAYBKZZ/qL9gQ5YrPfur /tw7AFMze1mIJO5nMBIKiB1ATQ/lvhhSkJidMiO/lw9WcraG1Am/Z0C79KUOa3f8KxRT UPnw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from; bh=tze6FlNdLS0EdtYD8zwnU9lurDfrxWe7i3wbYVxiLHQ=; fh=2uEWnGGvEpdqFtUqKQh3Y6uaGNgTGNOI0L2cxn3xouc=; b=i/DYOy4GfMEEkMS5/cuilLg/9qSQpQk+llmX//6gCIN/sJTS59YrZtl7bHUSShlXYj p6NWp6whkpMYqg6iTKe9t7IqpOUSd1UvPMFL+xLWTi5h6rOKrUVQlmXsuRbzRFRvYQhW sGSo+iZlSoLJK1QjSYkFMzJtCk3GbCUrkdWAIUldRAVnNGOCQwg6Tm8raNMniKxwCgk3 zJKUFtgwyL709GVPiweTSuTc0kQ98yIYzp9hOSThNgAubNYtTf8Cg02aa5sNm4Myo3F8 jHd6sRjT8J3t9hUltlwfeDxR2+V+d+Av9mT3GjmkBjLOz6P/EErqqL5tuKqKOrVxBkFj PeTQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id bx26-20020a056a02051a00b005b9755fd511si2375330pgb.182.2023.11.07.05.51.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Nov 2023 05:51:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 8EFA5813898A; Tue, 7 Nov 2023 05:50:30 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234390AbjKGNuY (ORCPT <rfc822;lhua1029@gmail.com> + 32 others); Tue, 7 Nov 2023 08:50:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233877AbjKGNuF (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 7 Nov 2023 08:50:05 -0500 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CECD2136; Tue, 7 Nov 2023 05:48:14 -0800 (PST) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4SPq2k02yMz9y19W; Tue, 7 Nov 2023 21:34:54 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwDHtXXdP0pltoA3AA--.60646S4; Tue, 07 Nov 2023 14:47:46 +0100 (CET) From: Roberto Sassu <roberto.sassu@huaweicloud.com> To: viro@zeniv.linux.org.uk, brauner@kernel.org, chuck.lever@oracle.com, jlayton@kernel.org, neilb@suse.de, kolga@netapp.com, Dai.Ngo@oracle.com, tom@talpey.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, dhowells@redhat.com, jarkko@kernel.org, stephen.smalley.work@gmail.com, eparis@parisplace.org, casey@schaufler-ca.com, mic@digikod.net Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-security-module@vger.kernel.org, linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, selinux@vger.kernel.org, Roberto Sassu <roberto.sassu@huawei.com> Subject: [PATCH v5 22/23] integrity: Move integrity functions to the LSM infrastructure Date: Tue, 7 Nov 2023 14:40:11 +0100 Message-Id: <20231107134012.682009-23-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231107134012.682009-1-roberto.sassu@huaweicloud.com> References: <20231107134012.682009-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID: LxC2BwDHtXXdP0pltoA3AA--.60646S4 X-Coremail-Antispam: 1UD129KBjvJXoW3AF13XF15ZF17Jr17Cr1rJFb_yoW7Kw1fpF srKay5Jrn5ZFy29FWkAF45ua1fK39Ygry7Wrs8Cw1vyFyqvr10qF4DAry5uFy3WrWrtr1I qFsI9r4UCr1Dt3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBYb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJr0_GcWl84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1Y6r17McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2I x0cI8IcVAFwI0_Xr0_Ar1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4UJVW0owCI42IY6xAI w20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x 0267AKxVWxJr0_GcJvcSsGvfC2KfnxnUUI43ZEXa7IU1o5l5UUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAOBF1jj5YbkwAAsk X-CFilter-Loop: Reflected X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Tue, 07 Nov 2023 05:50:30 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1781913459156289072 X-GMAIL-MSGID: 1781913459156289072 |
Series |
security: Move IMA and EVM to the LSM infrastructure
|
|
Commit Message
Roberto Sassu
Nov. 7, 2023, 1:40 p.m. UTC
From: Roberto Sassu <roberto.sassu@huawei.com> Remove hardcoded calls to integrity functions from the LSM infrastructure and, instead, register them in integrity_lsm_init() with the IMA or EVM LSM ID (the first non-NULL returned by ima_get_lsm_id() and evm_get_lsm_id()). Also move the global declaration of integrity_inode_get() to security/integrity/integrity.h, so that the function can be still called by IMA. Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> --- include/linux/integrity.h | 26 -------------------------- security/integrity/iint.c | 30 +++++++++++++++++++++++++++++- security/integrity/integrity.h | 7 +++++++ security/security.c | 9 +-------- 4 files changed, 37 insertions(+), 35 deletions(-)
Comments
On 11/7/2023 5:40 AM, Roberto Sassu wrote: > From: Roberto Sassu <roberto.sassu@huawei.com> > > Remove hardcoded calls to integrity functions from the LSM infrastructure > and, instead, register them in integrity_lsm_init() with the IMA or EVM > LSM ID (the first non-NULL returned by ima_get_lsm_id() and > evm_get_lsm_id()). > > Also move the global declaration of integrity_inode_get() to > security/integrity/integrity.h, so that the function can be still called by > IMA. > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> Reviewed-by: Casey Schaufler <casey@schaufler-ca.com> > --- > include/linux/integrity.h | 26 -------------------------- > security/integrity/iint.c | 30 +++++++++++++++++++++++++++++- > security/integrity/integrity.h | 7 +++++++ > security/security.c | 9 +-------- > 4 files changed, 37 insertions(+), 35 deletions(-) > > diff --git a/include/linux/integrity.h b/include/linux/integrity.h > index 2ea0f2f65ab6..afaae7ad26f4 100644 > --- a/include/linux/integrity.h > +++ b/include/linux/integrity.h > @@ -21,38 +21,12 @@ enum integrity_status { > > /* List of EVM protected security xattrs */ > #ifdef CONFIG_INTEGRITY > -extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); > -extern void integrity_inode_free(struct inode *inode); > extern void __init integrity_load_keys(void); > > #else > -static inline struct integrity_iint_cache * > - integrity_inode_get(struct inode *inode) > -{ > - return NULL; > -} > - > -static inline void integrity_inode_free(struct inode *inode) > -{ > - return; > -} > - > static inline void integrity_load_keys(void) > { > } > #endif /* CONFIG_INTEGRITY */ > > -#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > - > -extern int integrity_kernel_module_request(char *kmod_name); > - > -#else > - > -static inline int integrity_kernel_module_request(char *kmod_name) > -{ > - return 0; > -} > - > -#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ > - > #endif /* _LINUX_INTEGRITY_H */ > diff --git a/security/integrity/iint.c b/security/integrity/iint.c > index 0b0ac71142e8..882fde2a2607 100644 > --- a/security/integrity/iint.c > +++ b/security/integrity/iint.c > @@ -171,7 +171,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) > * > * Free the integrity information(iint) associated with an inode. > */ > -void integrity_inode_free(struct inode *inode) > +static void integrity_inode_free(struct inode *inode) > { > struct integrity_iint_cache *iint; > > @@ -193,11 +193,39 @@ static void iint_init_once(void *foo) > memset(iint, 0, sizeof(*iint)); > } > > +static struct security_hook_list integrity_hooks[] __ro_after_init = { > + LSM_HOOK_INIT(inode_free_security, integrity_inode_free), > +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > + LSM_HOOK_INIT(kernel_module_request, integrity_kernel_module_request), > +#endif > +}; > + > +/* > + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to > + * ensure that the management of integrity metadata is working at the time > + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep > + * the original ordering of IMA and EVM functions as when they were hardcoded. > + */ > static int __init integrity_lsm_init(void) > { > + const struct lsm_id *lsmid; > + > iint_cache = > kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), > 0, SLAB_PANIC, iint_init_once); > + /* > + * Obtain either the IMA or EVM LSM ID to register integrity-specific > + * hooks under that LSM, since there is no LSM ID assigned to the > + * 'integrity' LSM. > + */ > + lsmid = ima_get_lsm_id(); > + if (!lsmid) > + lsmid = evm_get_lsm_id(); > + /* No point in continuing, since both IMA and EVM are disabled. */ > + if (!lsmid) > + return 0; > + > + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); > init_ima_lsm(); > init_evm_lsm(); > return 0; > diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h > index 7534ec06324e..e4df82d6f6e7 100644 > --- a/security/integrity/integrity.h > +++ b/security/integrity/integrity.h > @@ -180,6 +180,7 @@ struct integrity_iint_cache { > * integrity data associated with an inode. > */ > struct integrity_iint_cache *integrity_iint_find(struct inode *inode); > +struct integrity_iint_cache *integrity_inode_get(struct inode *inode); > > int integrity_kernel_read(struct file *file, loff_t offset, > void *addr, unsigned long count); > @@ -266,12 +267,18 @@ static inline int __init integrity_load_cert(const unsigned int id, > #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > int asymmetric_verify(struct key *keyring, const char *sig, > int siglen, const char *data, int datalen); > +int integrity_kernel_module_request(char *kmod_name); > #else > static inline int asymmetric_verify(struct key *keyring, const char *sig, > int siglen, const char *data, int datalen) > { > return -EOPNOTSUPP; > } > + > +static inline int integrity_kernel_module_request(char *kmod_name) > +{ > + return 0; > +} > #endif > > #ifdef CONFIG_IMA_APPRAISE_MODSIG > diff --git a/security/security.c b/security/security.c > index 9703549b6ddc..0d9eaa4cd260 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -19,7 +19,6 @@ > #include <linux/kernel.h> > #include <linux/kernel_read_file.h> > #include <linux/lsm_hooks.h> > -#include <linux/integrity.h> > #include <linux/fsnotify.h> > #include <linux/mman.h> > #include <linux/mount.h> > @@ -1597,7 +1596,6 @@ static void inode_free_by_rcu(struct rcu_head *head) > */ > void security_inode_free(struct inode *inode) > { > - integrity_inode_free(inode); > call_void_hook(inode_free_security, inode); > /* > * The inode may still be referenced in a path walk and > @@ -3182,12 +3180,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) > */ > int security_kernel_module_request(char *kmod_name) > { > - int ret; > - > - ret = call_int_hook(kernel_module_request, 0, kmod_name); > - if (ret) > - return ret; > - return integrity_kernel_module_request(kmod_name); > + return call_int_hook(kernel_module_request, 0, kmod_name); > } > > /**
On Nov 7, 2023 Roberto Sassu <roberto.sassu@huaweicloud.com> wrote: > > Remove hardcoded calls to integrity functions from the LSM infrastructure > and, instead, register them in integrity_lsm_init() with the IMA or EVM > LSM ID (the first non-NULL returned by ima_get_lsm_id() and > evm_get_lsm_id()). > > Also move the global declaration of integrity_inode_get() to > security/integrity/integrity.h, so that the function can be still called by > IMA. > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> > Reviewed-by: Casey Schaufler <casey@schaufler-ca.com> > Reviewed-by: Mimi Zohar <zohar@linux.ibm.com> > --- > include/linux/integrity.h | 26 -------------------------- > security/integrity/iint.c | 30 +++++++++++++++++++++++++++++- > security/integrity/integrity.h | 7 +++++++ > security/security.c | 9 +-------- > 4 files changed, 37 insertions(+), 35 deletions(-) ... > diff --git a/security/integrity/iint.c b/security/integrity/iint.c > index 0b0ac71142e8..882fde2a2607 100644 > --- a/security/integrity/iint.c > +++ b/security/integrity/iint.c > @@ -171,7 +171,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) > * > * Free the integrity information(iint) associated with an inode. > */ > -void integrity_inode_free(struct inode *inode) > +static void integrity_inode_free(struct inode *inode) > { > struct integrity_iint_cache *iint; > > @@ -193,11 +193,39 @@ static void iint_init_once(void *foo) > memset(iint, 0, sizeof(*iint)); > } > > +static struct security_hook_list integrity_hooks[] __ro_after_init = { > + LSM_HOOK_INIT(inode_free_security, integrity_inode_free), > +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > + LSM_HOOK_INIT(kernel_module_request, integrity_kernel_module_request), > +#endif > +}; > + > +/* > + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to > + * ensure that the management of integrity metadata is working at the time > + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep > + * the original ordering of IMA and EVM functions as when they were hardcoded. > + */ > static int __init integrity_lsm_init(void) > { > + const struct lsm_id *lsmid; > + > iint_cache = > kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), > 0, SLAB_PANIC, iint_init_once); > + /* > + * Obtain either the IMA or EVM LSM ID to register integrity-specific > + * hooks under that LSM, since there is no LSM ID assigned to the > + * 'integrity' LSM. > + */ > + lsmid = ima_get_lsm_id(); > + if (!lsmid) > + lsmid = evm_get_lsm_id(); > + /* No point in continuing, since both IMA and EVM are disabled. */ > + if (!lsmid) > + return 0; > + > + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); Ooof. I understand, or at least I think I understand, why the above hack is needed, but I really don't like the idea of @integrity_hooks jumping between IMA and EVM depending on how the kernel is configured. Just to make sure I'm understanding things correctly, the "integrity" LSM exists to ensure the proper hook ordering between IMA/EVM, shared metadata management for IMA/EVM, and a little bit of a hack to solve some kernel module loading issues with signatures. Is that correct? I see that patch 23/23 makes some nice improvements to the metadata management, moving them into LSM security blobs, but it appears that they are still shared, and thus the requirement is still there for an "integrity" LSM to manage the shared blobs. I'd like to hear everyone's honest opinion on this next question: do we have any hope of separating IMA and EVM so they are independent (ignore the ordering issues for a moment), or are we always going to need to have the "integrity" LSM to manage shared resources, hooks, etc.? > init_ima_lsm(); > init_evm_lsm(); > return 0; -- paul-moore.com
On Wed, 2023-11-15 at 23:33 -0500, Paul Moore wrote: > On Nov 7, 2023 Roberto Sassu <roberto.sassu@huaweicloud.com> wrote: > > > > Remove hardcoded calls to integrity functions from the LSM infrastructure > > and, instead, register them in integrity_lsm_init() with the IMA or EVM > > LSM ID (the first non-NULL returned by ima_get_lsm_id() and > > evm_get_lsm_id()). > > > > Also move the global declaration of integrity_inode_get() to > > security/integrity/integrity.h, so that the function can be still called by > > IMA. > > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> > > Reviewed-by: Casey Schaufler <casey@schaufler-ca.com> > > Reviewed-by: Mimi Zohar <zohar@linux.ibm.com> > > --- > > include/linux/integrity.h | 26 -------------------------- > > security/integrity/iint.c | 30 +++++++++++++++++++++++++++++- > > security/integrity/integrity.h | 7 +++++++ > > security/security.c | 9 +-------- > > 4 files changed, 37 insertions(+), 35 deletions(-) > > ... > > > diff --git a/security/integrity/iint.c b/security/integrity/iint.c > > index 0b0ac71142e8..882fde2a2607 100644 > > --- a/security/integrity/iint.c > > +++ b/security/integrity/iint.c > > @@ -171,7 +171,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) > > * > > * Free the integrity information(iint) associated with an inode. > > */ > > -void integrity_inode_free(struct inode *inode) > > +static void integrity_inode_free(struct inode *inode) > > { > > struct integrity_iint_cache *iint; > > > > @@ -193,11 +193,39 @@ static void iint_init_once(void *foo) > > memset(iint, 0, sizeof(*iint)); > > } > > > > +static struct security_hook_list integrity_hooks[] __ro_after_init = { > > + LSM_HOOK_INIT(inode_free_security, integrity_inode_free), > > +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS > > + LSM_HOOK_INIT(kernel_module_request, integrity_kernel_module_request), > > +#endif > > +}; > > + > > +/* > > + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to > > + * ensure that the management of integrity metadata is working at the time > > + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep > > + * the original ordering of IMA and EVM functions as when they were hardcoded. > > + */ > > static int __init integrity_lsm_init(void) > > { > > + const struct lsm_id *lsmid; > > + > > iint_cache = > > kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), > > 0, SLAB_PANIC, iint_init_once); > > + /* > > + * Obtain either the IMA or EVM LSM ID to register integrity-specific > > + * hooks under that LSM, since there is no LSM ID assigned to the > > + * 'integrity' LSM. > > + */ > > + lsmid = ima_get_lsm_id(); > > + if (!lsmid) > > + lsmid = evm_get_lsm_id(); > > + /* No point in continuing, since both IMA and EVM are disabled. */ > > + if (!lsmid) > > + return 0; > > + > > + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); > > Ooof. I understand, or at least I think I understand, why the above > hack is needed, but I really don't like the idea of @integrity_hooks > jumping between IMA and EVM depending on how the kernel is configured. > > Just to make sure I'm understanding things correctly, the "integrity" > LSM exists to ensure the proper hook ordering between IMA/EVM, shared > metadata management for IMA/EVM, and a little bit of a hack to solve > some kernel module loading issues with signatures. Is that correct? > > I see that patch 23/23 makes some nice improvements to the metadata > management, moving them into LSM security blobs, but it appears that > they are still shared, and thus the requirement is still there for > an "integrity" LSM to manage the shared blobs. Yes, all is correct. > I'd like to hear everyone's honest opinion on this next question: do > we have any hope of separating IMA and EVM so they are independent > (ignore the ordering issues for a moment), or are we always going to > need to have the "integrity" LSM to manage shared resources, hooks, > etc.? I think it should not be technically difficult to do it. But, it would be very important to understand all the implications of doing those changes. Sorry, for now I don't see an immediate need to do that, other than solving this LSM naming issue. I tried to find the best solution I could. Thanks Roberto > > init_ima_lsm(); > > init_evm_lsm(); > > return 0; > > -- > paul-moore.com
On Thu, Nov 16, 2023 at 5:08 AM Roberto Sassu <roberto.sassu@huaweicloud.com> wrote: > On Wed, 2023-11-15 at 23:33 -0500, Paul Moore wrote: > > On Nov 7, 2023 Roberto Sassu <roberto.sassu@huaweicloud.com> wrote: ... > > > +/* > > > + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to > > > + * ensure that the management of integrity metadata is working at the time > > > + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep > > > + * the original ordering of IMA and EVM functions as when they were hardcoded. > > > + */ > > > static int __init integrity_lsm_init(void) > > > { > > > + const struct lsm_id *lsmid; > > > + > > > iint_cache = > > > kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), > > > 0, SLAB_PANIC, iint_init_once); > > > + /* > > > + * Obtain either the IMA or EVM LSM ID to register integrity-specific > > > + * hooks under that LSM, since there is no LSM ID assigned to the > > > + * 'integrity' LSM. > > > + */ > > > + lsmid = ima_get_lsm_id(); > > > + if (!lsmid) > > > + lsmid = evm_get_lsm_id(); > > > + /* No point in continuing, since both IMA and EVM are disabled. */ > > > + if (!lsmid) > > > + return 0; > > > + > > > + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); > > > > Ooof. I understand, or at least I think I understand, why the above > > hack is needed, but I really don't like the idea of @integrity_hooks > > jumping between IMA and EVM depending on how the kernel is configured. > > > > Just to make sure I'm understanding things correctly, the "integrity" > > LSM exists to ensure the proper hook ordering between IMA/EVM, shared > > metadata management for IMA/EVM, and a little bit of a hack to solve > > some kernel module loading issues with signatures. Is that correct? > > > > I see that patch 23/23 makes some nice improvements to the metadata > > management, moving them into LSM security blobs, but it appears that > > they are still shared, and thus the requirement is still there for > > an "integrity" LSM to manage the shared blobs. > > Yes, all is correct. Thanks for the clarification, more on this below. > > I'd like to hear everyone's honest opinion on this next question: do > > we have any hope of separating IMA and EVM so they are independent > > (ignore the ordering issues for a moment), or are we always going to > > need to have the "integrity" LSM to manage shared resources, hooks, > > etc.? > > I think it should not be technically difficult to do it. But, it would > be very important to understand all the implications of doing those > changes. > > Sorry, for now I don't see an immediate need to do that, other than > solving this LSM naming issue. I tried to find the best solution I > could. I first want to say that I think you've done a great job thus far, and I'm very grateful for the work you've done. We can always use more help in the kernel security space and I'm very happy to see your contributions - thank you :) I'm concerned about the integrity LSM because it isn't really a LSM, it is simply an implementation artifact from a time when only one LSM was enabled. Now that we have basic support for stacking LSMs, as we promote integrity/IMA/EVM I think this is the perfect time to move away from the "integrity" portion and integrate the necessary functionality into the IMA and EVM LSMs. This is even more important now that we are looking at making the LSMs more visible to userspace via syscalls; how would you explain to a developer or user the need for an "integrity" LSM along with the IMA and EVM LSMs? Let's look at the three things the the integrity code provides in this patchset: * IMA/EVM hook ordering For better or worse, we have requirements on LSM ordering today that are enforced only by convention, the BPF LSM being the perfect example. As long as we document this in Kconfig I think we are okay. * Shared metadata Looking at the integrity_iint_cache struct at the end of your patchset I see the following: struct integrity_iint_cache { struct mutex mutex; struct inode *inode; u64 version; unsigned long flags; unsigned long measured_pcrs; unsigned long atomic_flags; enum integrity_status ima_file_status:4; enum integrity_status ima_mmap_status:4; enum integrity_status ima_bprm_status:4; enum integrity_status ima_read_status:4; enum integrity_status ima_creds_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; }; Now that we are stashing the metadata in the inode, we should be able to remove the @inode field back pointer. It seems like we could duplicate @mutex and @version without problem. I only see the @measured_pcrs, @atomic_flags used in the IMA code. I only see the @ima_XXX_status fields using in the IMA code, and the @evm_status used in the EVM code. I only see the @ima_hash field used by the IMA code. I do see both IMA and EVM using the @flags field, but only one case (IMA_NEW_FILE) where one LSM (EVM) looks for another flags (IMA). I'm not sure how difficult that would be to untangle, but I imagine we could do something here; if we had to, we could make EVM be dependent on IMA in Kconfig and add a function call to check on the inode status. Although I hope we could find a better solution. * Kernel module loading hook (integrity_kernel_module_request(...)) My guess is that this is really an IMA hook, but I can't say for certain. If it is needed for EVM we could always duplicate it across the IMA and EVM LSMs, it is trivially small and one extra strcmp() at kernel module load time doesn't seem awful to me.
On Fri, 2023-11-17 at 16:22 -0500, Paul Moore wrote: > On Thu, Nov 16, 2023 at 5:08 AM Roberto Sassu > <roberto.sassu@huaweicloud.com> wrote: > > On Wed, 2023-11-15 at 23:33 -0500, Paul Moore wrote: > > > On Nov 7, 2023 Roberto Sassu <roberto.sassu@huaweicloud.com> wrote: > > ... > > > > > +/* > > > > + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to > > > > + * ensure that the management of integrity metadata is working at the time > > > > + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep > > > > + * the original ordering of IMA and EVM functions as when they were hardcoded. > > > > + */ > > > > static int __init integrity_lsm_init(void) > > > > { > > > > + const struct lsm_id *lsmid; > > > > + > > > > iint_cache = > > > > kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), > > > > 0, SLAB_PANIC, iint_init_once); > > > > + /* > > > > + * Obtain either the IMA or EVM LSM ID to register integrity-specific > > > > + * hooks under that LSM, since there is no LSM ID assigned to the > > > > + * 'integrity' LSM. > > > > + */ > > > > + lsmid = ima_get_lsm_id(); > > > > + if (!lsmid) > > > > + lsmid = evm_get_lsm_id(); > > > > + /* No point in continuing, since both IMA and EVM are disabled. */ > > > > + if (!lsmid) > > > > + return 0; > > > > + > > > > + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); > > > > > > Ooof. I understand, or at least I think I understand, why the above > > > hack is needed, but I really don't like the idea of @integrity_hooks > > > jumping between IMA and EVM depending on how the kernel is configured. > > > > > > Just to make sure I'm understanding things correctly, the "integrity" > > > LSM exists to ensure the proper hook ordering between IMA/EVM, shared > > > metadata management for IMA/EVM, and a little bit of a hack to solve > > > some kernel module loading issues with signatures. Is that correct? > > > > > > I see that patch 23/23 makes some nice improvements to the metadata > > > management, moving them into LSM security blobs, but it appears that > > > they are still shared, and thus the requirement is still there for > > > an "integrity" LSM to manage the shared blobs. > > > > Yes, all is correct. > > Thanks for the clarification, more on this below. > > > > I'd like to hear everyone's honest opinion on this next question: do > > > we have any hope of separating IMA and EVM so they are independent > > > (ignore the ordering issues for a moment), or are we always going to > > > need to have the "integrity" LSM to manage shared resources, hooks, > > > etc.? > > > > I think it should not be technically difficult to do it. But, it would > > be very important to understand all the implications of doing those > > changes. > > > > Sorry, for now I don't see an immediate need to do that, other than > > solving this LSM naming issue. I tried to find the best solution I > > could. > > I first want to say that I think you've done a great job thus far, and > I'm very grateful for the work you've done. We can always use more > help in the kernel security space and I'm very happy to see your > contributions - thank you :) Thank you! > I'm concerned about the integrity LSM because it isn't really a LSM, > it is simply an implementation artifact from a time when only one LSM > was enabled. Now that we have basic support for stacking LSMs, as we > promote integrity/IMA/EVM I think this is the perfect time to move > away from the "integrity" portion and integrate the necessary > functionality into the IMA and EVM LSMs. This is even more important > now that we are looking at making the LSMs more visible to userspace > via syscalls; how would you explain to a developer or user the need > for an "integrity" LSM along with the IMA and EVM LSMs? > > Let's look at the three things the the integrity code provides in this patchset: > > * IMA/EVM hook ordering > > For better or worse, we have requirements on LSM ordering today that > are enforced only by convention, the BPF LSM being the perfect > example. As long as we document this in Kconfig I think we are okay. > > * Shared metadata > > Looking at the integrity_iint_cache struct at the end of your patchset > I see the following: > > struct integrity_iint_cache { > struct mutex mutex; > struct inode *inode; > u64 version; > unsigned long flags; > unsigned long measured_pcrs; > unsigned long atomic_flags; > enum integrity_status ima_file_status:4; > enum integrity_status ima_mmap_status:4; > enum integrity_status ima_bprm_status:4; > enum integrity_status ima_read_status:4; > enum integrity_status ima_creds_status:4; > enum integrity_status evm_status:4; > struct ima_digest_data *ima_hash; > }; > > Now that we are stashing the metadata in the inode, we should be able > to remove the @inode field back pointer. It seems like we could > duplicate @mutex and @version without problem. > > I only see the @measured_pcrs, @atomic_flags used in the IMA code. > > I only see the @ima_XXX_status fields using in the IMA code, and the > @evm_status used in the EVM code. > > I only see the @ima_hash field used by the IMA code. > > I do see both IMA and EVM using the @flags field, but only one case > (IMA_NEW_FILE) where one LSM (EVM) looks for another flags (IMA). I'm > not sure how difficult that would be to untangle, but I imagine we > could do something here; if we had to, we could make EVM be dependent > on IMA in Kconfig and add a function call to check on the inode > status. Although I hope we could find a better solution. > > * Kernel module loading hook (integrity_kernel_module_request(...)) > > My guess is that this is really an IMA hook, but I can't say for > certain. If it is needed for EVM we could always duplicate it across > the IMA and EVM LSMs, it is trivially small and one extra strcmp() at > kernel module load time doesn't seem awful to me. Ok... so, for now I'm trying to separate them just to see if it is possible. Will send just the integrity-related patches shortly. Thanks Roberto
diff --git a/include/linux/integrity.h b/include/linux/integrity.h index 2ea0f2f65ab6..afaae7ad26f4 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h @@ -21,38 +21,12 @@ enum integrity_status { /* List of EVM protected security xattrs */ #ifdef CONFIG_INTEGRITY -extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); -extern void integrity_inode_free(struct inode *inode); extern void __init integrity_load_keys(void); #else -static inline struct integrity_iint_cache * - integrity_inode_get(struct inode *inode) -{ - return NULL; -} - -static inline void integrity_inode_free(struct inode *inode) -{ - return; -} - static inline void integrity_load_keys(void) { } #endif /* CONFIG_INTEGRITY */ -#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS - -extern int integrity_kernel_module_request(char *kmod_name); - -#else - -static inline int integrity_kernel_module_request(char *kmod_name) -{ - return 0; -} - -#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */ - #endif /* _LINUX_INTEGRITY_H */ diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 0b0ac71142e8..882fde2a2607 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -171,7 +171,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) * * Free the integrity information(iint) associated with an inode. */ -void integrity_inode_free(struct inode *inode) +static void integrity_inode_free(struct inode *inode) { struct integrity_iint_cache *iint; @@ -193,11 +193,39 @@ static void iint_init_once(void *foo) memset(iint, 0, sizeof(*iint)); } +static struct security_hook_list integrity_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_free_security, integrity_inode_free), +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS + LSM_HOOK_INIT(kernel_module_request, integrity_kernel_module_request), +#endif +}; + +/* + * Perform the initialization of the 'integrity', 'ima' and 'evm' LSMs to + * ensure that the management of integrity metadata is working at the time + * IMA and EVM hooks are registered to the LSM infrastructure, and to keep + * the original ordering of IMA and EVM functions as when they were hardcoded. + */ static int __init integrity_lsm_init(void) { + const struct lsm_id *lsmid; + iint_cache = kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache), 0, SLAB_PANIC, iint_init_once); + /* + * Obtain either the IMA or EVM LSM ID to register integrity-specific + * hooks under that LSM, since there is no LSM ID assigned to the + * 'integrity' LSM. + */ + lsmid = ima_get_lsm_id(); + if (!lsmid) + lsmid = evm_get_lsm_id(); + /* No point in continuing, since both IMA and EVM are disabled. */ + if (!lsmid) + return 0; + + security_add_hooks(integrity_hooks, ARRAY_SIZE(integrity_hooks), lsmid); init_ima_lsm(); init_evm_lsm(); return 0; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 7534ec06324e..e4df82d6f6e7 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -180,6 +180,7 @@ struct integrity_iint_cache { * integrity data associated with an inode. */ struct integrity_iint_cache *integrity_iint_find(struct inode *inode); +struct integrity_iint_cache *integrity_inode_get(struct inode *inode); int integrity_kernel_read(struct file *file, loff_t offset, void *addr, unsigned long count); @@ -266,12 +267,18 @@ static inline int __init integrity_load_cert(const unsigned int id, #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen); +int integrity_kernel_module_request(char *kmod_name); #else static inline int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen) { return -EOPNOTSUPP; } + +static inline int integrity_kernel_module_request(char *kmod_name) +{ + return 0; +} #endif #ifdef CONFIG_IMA_APPRAISE_MODSIG diff --git a/security/security.c b/security/security.c index 9703549b6ddc..0d9eaa4cd260 100644 --- a/security/security.c +++ b/security/security.c @@ -19,7 +19,6 @@ #include <linux/kernel.h> #include <linux/kernel_read_file.h> #include <linux/lsm_hooks.h> -#include <linux/integrity.h> #include <linux/fsnotify.h> #include <linux/mman.h> #include <linux/mount.h> @@ -1597,7 +1596,6 @@ static void inode_free_by_rcu(struct rcu_head *head) */ void security_inode_free(struct inode *inode) { - integrity_inode_free(inode); call_void_hook(inode_free_security, inode); /* * The inode may still be referenced in a path walk and @@ -3182,12 +3180,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) */ int security_kernel_module_request(char *kmod_name) { - int ret; - - ret = call_int_hook(kernel_module_request, 0, kmod_name); - if (ret) - return ret; - return integrity_kernel_module_request(kmod_name); + return call_int_hook(kernel_module_request, 0, kmod_name); } /**