From patchwork Sat Jun 10 07:57:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13274761 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71279A950 for ; Sat, 10 Jun 2023 07:58:46 +0000 (UTC) Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E9703CC; Sat, 10 Jun 2023 00:58:43 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QdVRy47bVz9y5YV; Sat, 10 Jun 2023 15:48:14 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBH0AsGLYRklC8oAw--.4566S3; Sat, 10 Jun 2023 08:58:20 +0100 (CET) From: Roberto Sassu To: zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, stephen.smalley.work@gmail.com, eparis@parisplace.org, casey@schaufler-ca.com Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org, bpf@vger.kernel.org, kpsingh@kernel.org, keescook@chromium.org, nicolas.bouchinet@clip-os.org, Roberto Sassu Subject: [PATCH v12 1/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Date: Sat, 10 Jun 2023 09:57:35 +0200 Message-Id: <20230610075738.3273764-2-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> References: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBH0AsGLYRklC8oAw--.4566S3 X-Coremail-Antispam: 1UD129KBjvAXoW3Kr1DWw4kZFyUuF4xJr1xAFb_yoW8GF1fuo WxJwnrXr40gr13GrWYgFn7JFZrZayfWr4fJr1Yvr4UAa4ay34DCw13Ja15Xa13XryrKr10 q3srAay8XFW2qF98n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYJ7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr 4l82xGYIkIc2x26xkF7I0E14v26r4j6ryUM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr0_Gr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMc Ij6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_ Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2I x0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j6F4UMIIF0xvE42xK 8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6xkF7I 0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjxU2mL9UUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj45+YgABsj X-CFilter-Loop: Reflected X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KHOP_HELO_FCRDNS, MAY_BE_FORGED,PDS_RDNS_DYNAMIC_FP,RCVD_IN_MSPIKE_BL,RCVD_IN_MSPIKE_L3, RDNS_DYNAMIC,SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Roberto Sassu Currently, the LSM infrastructure supports only one LSM providing an xattr and EVM calculating the HMAC on that xattr, plus other inode metadata. Allow all LSMs to provide one or multiple xattrs, by extending the security blob reservation mechanism. Introduce the new lbs_xattr_count field of the lsm_blob_sizes structure, so that each LSM can specify how many xattrs it needs, and the LSM infrastructure knows how many xattr slots it should allocate. Modify the inode_init_security hook definition, by passing the full xattr array allocated in security_inode_init_security(), and the current number of xattr slots in that array filled by LSMs. The first parameter would allow EVM to access and calculate the HMAC on xattrs supplied by other LSMs, the second to not leave gaps in the xattr array, when an LSM requested but did not provide xattrs (e.g. if it is not initialized). Introduce lsm_get_xattr_slot(), which LSMs can call as many times as the number specified in the lbs_xattr_count field of the lsm_blob_sizes structure. During each call, lsm_get_xattr_slot() increments the number of filled xattrs, so that at the next invocation it returns the next xattr slot to fill. Cleanup security_inode_init_security(). Unify the !initxattrs and initxattrs case by simply not allocating the new_xattrs array in the former. Update the documentation to reflect the changes, and fix the description of the xattr name, as it is not allocated anymore. Adapt both SELinux and Smack to use the new definition of the inode_init_security hook, and to call lsm_get_xattr_slot() to obtain and fill the reserved slots in the xattr array. Move the xattr->name assignment after the xattr->value one, so that it is done only in case of successful memory allocation. Finally, change the default return value of the inode_init_security hook from zero to -EOPNOTSUPP, so that BPF LSM correctly follows the hook conventions. Reported-by: Nicolas Bouchinet (EVM crash) Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/ Signed-off-by: Roberto Sassu --- include/linux/lsm_hook_defs.h | 6 +-- include/linux/lsm_hooks.h | 20 ++++++++++ security/security.c | 71 +++++++++++++++++++++++------------ security/selinux/hooks.c | 17 +++++---- security/smack/smack_lsm.c | 25 ++++++------ 5 files changed, 92 insertions(+), 47 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 6bb55e61e8e..a1896f90089 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -111,9 +111,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask, unsigned int obj_type) LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode) LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) -LSM_HOOK(int, 0, inode_init_security, struct inode *inode, - struct inode *dir, const struct qstr *qstr, const char **name, - void **value, size_t *len) +LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode, + struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, + int *xattr_count) LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, const struct qstr *name, const struct inode *context_inode) LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry, diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index ab2b2fafa4a..dcb5e5b5eb1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -28,6 +28,7 @@ #include #include #include +#include union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); @@ -63,8 +64,27 @@ struct lsm_blob_sizes { int lbs_ipc; int lbs_msg_msg; int lbs_task; + int lbs_xattr_count; /* number of xattr slots in new_xattrs array */ }; +/** + * lsm_get_xattr_slot - Return the next available slot and increment the index + * @xattrs: array storing LSM-provided xattrs + * @xattr_count: number of already stored xattrs (updated) + * + * Retrieve the first available slot in the @xattrs array to fill with an xattr, + * and increment @xattr_count. + * + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise. + */ +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs, + int *xattr_count) +{ + if (unlikely(!xattrs)) + return NULL; + return &xattrs[(*xattr_count)++]; +} + /* * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void * LSM hooks (in include/linux/lsm_hook_defs.h). diff --git a/security/security.c b/security/security.c index ee4f1cc4902..d5ef7df1ce4 100644 --- a/security/security.c +++ b/security/security.c @@ -31,8 +31,6 @@ #include #include -#define MAX_LSM_EVM_XATTR 2 - /* How many LSMs were built into the kernel? */ #define LSM_COUNT (__end_lsm_info - __start_lsm_info) @@ -212,6 +210,8 @@ 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_xattr_count, + &blob_sizes.lbs_xattr_count); } /* Prepare LSM for initialization. */ @@ -378,6 +378,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("xattr slots = %d\n", blob_sizes.lbs_xattr_count); /* * Create any kmem_caches needed for blobs @@ -1591,11 +1592,15 @@ EXPORT_SYMBOL(security_dentry_create_files_as); * created inode and set up the incore security field for the new inode. This * hook is called by the fs code as part of the inode creation transaction and * provides for atomic labeling of the inode, unlike the post_create/mkdir/... - * hooks called by the VFS. The hook function is expected to allocate the name - * and value via kmalloc, with the caller being responsible for calling kfree - * after using them. If the security module does not use security attributes - * or does not wish to put a security attribute on this particular inode, then - * it should return -EOPNOTSUPP to skip this processing. + * hooks called by the VFS. The hook function is expected to populate the + * @xattrs array, by calling lsm_get_xattr_slot() to retrieve the slots + * reserved by the security module with the lbs_xattr_count field of the + * lsm_blob_sizes structure. For each slot, the hook function should set ->name + * to the attribute name suffix (e.g. selinux), to allocate ->value (will be + * freed by the caller) and set it to the attribute value, to set ->value_len to + * the length of the value. If the security module does not use security + * attributes or does not wish to put a security attribute on this particular + * inode, then it should return -EOPNOTSUPP to skip this processing. * * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is * needed, or -ENOMEM on memory allocation failure. @@ -1604,33 +1609,51 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const initxattrs initxattrs, void *fs_data) { - struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1]; - struct xattr *lsm_xattr, *evm_xattr, *xattr; - int ret; + struct security_hook_list *P; + struct xattr *new_xattrs = NULL; + int ret = -EOPNOTSUPP, xattr_count = 0; if (unlikely(IS_PRIVATE(inode))) return 0; - if (!initxattrs) - return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, - dir, qstr, NULL, NULL, NULL); - memset(new_xattrs, 0, sizeof(new_xattrs)); - lsm_xattr = new_xattrs; - ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr, - &lsm_xattr->name, - &lsm_xattr->value, - &lsm_xattr->value_len); - if (ret) + if (!blob_sizes.lbs_xattr_count) + return 0; + + if (initxattrs) { + /* Allocate +1 for EVM and +1 as terminator. */ + new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2, + sizeof(*new_xattrs), GFP_NOFS); + if (!new_xattrs) + return -ENOMEM; + } + + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, + list) { + ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs, + &xattr_count); + if (ret && ret != -EOPNOTSUPP) + goto out; + /* + * As documented in lsm_hooks.h, -EOPNOTSUPP in this context + * means that the LSM is not willing to provide an xattr, not + * that it wants to signal an error. Thus, continue to invoke + * the remaining LSMs. + */ + } + + /* If initxattrs() is NULL, xattr_count is zero, skip the call. */ + if (!xattr_count) goto out; - evm_xattr = lsm_xattr + 1; - ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr); + ret = evm_inode_init_security(inode, new_xattrs, + &new_xattrs[xattr_count]); if (ret) goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: - for (xattr = new_xattrs; xattr->value != NULL; xattr++) - kfree(xattr->value); + for (; xattr_count > 0; xattr_count--) + kfree(new_xattrs[xattr_count - 1].value); + kfree(new_xattrs); return (ret == -EOPNOTSUPP) ? 0 : ret; } EXPORT_SYMBOL(security_inode_init_security); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79b4890e993..1d9fe7cdd01 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -104,6 +104,8 @@ #include "audit.h" #include "avc_ss.h" +#define SELINUX_INODE_INIT_XATTRS 1 + struct selinux_state selinux_state; /* SECMARK reference count */ @@ -2823,11 +2825,11 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, static int selinux_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, - const char **name, - void **value, size_t *len) + struct xattr *xattrs, int *xattr_count) { const struct task_security_struct *tsec = selinux_cred(current_cred()); struct superblock_security_struct *sbsec; + struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); u32 newsid, clen; int rc; char *context; @@ -2854,16 +2856,14 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, !(sbsec->flags & SBLABEL_MNT)) return -EOPNOTSUPP; - if (name) - *name = XATTR_SELINUX_SUFFIX; - - if (value && len) { + if (xattr) { rc = security_sid_to_context_force(newsid, &context, &clen); if (rc) return rc; - *value = context; - *len = clen; + xattr->value = context; + xattr->value_len = clen; + xattr->name = XATTR_SELINUX_SUFFIX; } return 0; @@ -6776,6 +6776,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = { .lbs_ipc = sizeof(struct ipc_security_struct), .lbs_msg_msg = sizeof(struct msg_security_struct), .lbs_superblock = sizeof(struct superblock_security_struct), + .lbs_xattr_count = SELINUX_INODE_INIT_XATTRS, }; #ifdef CONFIG_PERF_EVENTS diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6e270cf3fd3..25ade3819af 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -52,6 +52,8 @@ #define SMK_RECEIVING 1 #define SMK_SENDING 2 +#define SMACK_INODE_INIT_XATTRS 1 + #ifdef SMACK_IPV6_PORT_LABELING static DEFINE_MUTEX(smack_ipv6_lock); static LIST_HEAD(smk_ipv6_port_list); @@ -923,27 +925,24 @@ static int smack_inode_alloc_security(struct inode *inode) * @inode: the newly created inode * @dir: containing directory object * @qstr: unused - * @name: where to put the attribute name - * @value: where to put the attribute value - * @len: where to put the length of the attribute + * @xattrs: where to put the attributes + * @xattr_count: current number of LSM-provided xattrs (updated) * * Returns 0 if it all works out, -ENOMEM if there's no memory */ static int smack_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, const char **name, - void **value, size_t *len) + const struct qstr *qstr, + struct xattr *xattrs, int *xattr_count) { struct task_smack *tsp = smack_cred(current_cred()); struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_task(tsp); struct smack_known *isp = smk_of_inode(inode); struct smack_known *dsp = smk_of_inode(dir); + struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count); int may; - if (name) - *name = XATTR_SMACK_SUFFIX; - - if (value && len) { + if (xattr) { /* * If equal, transmuting already occurred in * smack_dentry_create_files_as(). No need to check again. @@ -975,11 +974,12 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, issp->smk_flags |= SMK_INODE_CHANGED; } - *value = kstrdup(isp->smk_known, GFP_NOFS); - if (*value == NULL) + xattr->value = kstrdup(isp->smk_known, GFP_NOFS); + if (!xattr->value) return -ENOMEM; - *len = strlen(isp->smk_known); + xattr->value_len = strlen(isp->smk_known); + xattr->name = XATTR_SMACK_SUFFIX; } return 0; @@ -4869,6 +4869,7 @@ struct lsm_blob_sizes smack_blob_sizes __ro_after_init = { .lbs_ipc = sizeof(struct smack_known *), .lbs_msg_msg = sizeof(struct smack_known *), .lbs_superblock = sizeof(struct superblock_smack), + .lbs_xattr_count = SMACK_INODE_INIT_XATTRS, }; static struct security_hook_list smack_hooks[] __ro_after_init = { From patchwork Sat Jun 10 07:57:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13274762 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 536666FCD for ; Sat, 10 Jun 2023 07:58:54 +0000 (UTC) Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C38323A8C; Sat, 10 Jun 2023 00:58:52 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4QdVS42nkqz9xqcr; Sat, 10 Jun 2023 15:48:20 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBH0AsGLYRklC8oAw--.4566S4; Sat, 10 Jun 2023 08:58:28 +0100 (CET) From: Roberto Sassu To: zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, stephen.smalley.work@gmail.com, eparis@parisplace.org, casey@schaufler-ca.com Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org, bpf@vger.kernel.org, kpsingh@kernel.org, keescook@chromium.org, nicolas.bouchinet@clip-os.org, Roberto Sassu Subject: [PATCH v12 2/4] smack: Set the SMACK64TRANSMUTE xattr in smack_inode_init_security() Date: Sat, 10 Jun 2023 09:57:36 +0200 Message-Id: <20230610075738.3273764-3-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> References: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBH0AsGLYRklC8oAw--.4566S4 X-Coremail-Antispam: 1UD129KBjvJXoWxAr4UCr17KFyDurW8Kw43GFg_yoWruF1DpF WUK3ZxKrs5tF1DWrWFyF4UWw4aka1rGrWUWr9xWrZav3ZrXw1xKFWkXr1YkF17Xrykur9Y qF4jqry5XFn0y37anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBFb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxAIw28IcxkI7V AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x07UC9aPUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4qCJAAAsf X-CFilter-Loop: Reflected X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KHOP_HELO_FCRDNS, MAY_BE_FORGED,PDS_RDNS_DYNAMIC_FP,RDNS_DYNAMIC,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Roberto Sassu With the newly added ability of LSMs to supply multiple xattrs, set SMACK64TRASMUTE in smack_inode_init_security(), instead of d_instantiate(). Do it by incrementing SMACK_INODE_INIT_XATTRS to 2 and by calling lsm_get_xattr_slot() a second time, if the transmuting conditions are met. The LSM infrastructure passes all xattrs provided by LSMs to the filesystems through the initxattrs() callback, so that filesystems can store xattrs in the disk. After the change, the SMK_INODE_TRANSMUTE inode flag is always set by d_instantiate() after fetching SMACK64TRANSMUTE from the disk. Before it was done by smack_inode_post_setxattr() as result of the __vfs_setxattr() call. Removing __vfs_setxattr() also prevents invalidating the EVM HMAC, by adding a new xattr without checking and updating the existing HMAC. Signed-off-by: Roberto Sassu Reviewed-by: Casey Schaufler --- security/smack/smack.h | 2 +- security/smack/smack_lsm.c | 45 ++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index aa15ff56ed6..041688e5a77 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -128,7 +128,7 @@ struct task_smack { #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ -#define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ +#define SMK_INODE_CHANGED 0x04 /* smack was transmuted (unused) */ #define SMK_INODE_IMPURE 0x08 /* involved in an impure transaction */ /* diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 25ade3819af..679156601a1 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -52,7 +52,14 @@ #define SMK_RECEIVING 1 #define SMK_SENDING 2 -#define SMACK_INODE_INIT_XATTRS 1 +/* + * Smack uses multiple xattrs. + * SMACK64 - for access control, + * SMACK64TRANSMUTE - label initialization, + * Not saved on files - SMACK64IPIN and SMACK64IPOUT, + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP + */ +#define SMACK_INODE_INIT_XATTRS 2 #ifdef SMACK_IPV6_PORT_LABELING static DEFINE_MUTEX(smack_ipv6_lock); @@ -935,7 +942,6 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, struct xattr *xattrs, int *xattr_count) { struct task_smack *tsp = smack_cred(current_cred()); - struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_task(tsp); struct smack_known *isp = smk_of_inode(inode); struct smack_known *dsp = smk_of_inode(dir); @@ -963,6 +969,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, if ((tsp->smk_task == tsp->smk_transmuted) || (may > 0 && ((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir))) { + struct xattr *xattr_transmute; + /* * The caller of smack_dentry_create_files_as() * should have overridden the current cred, so the @@ -971,7 +979,18 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, */ if (tsp->smk_task != tsp->smk_transmuted) isp = dsp; - issp->smk_flags |= SMK_INODE_CHANGED; + xattr_transmute = lsm_get_xattr_slot(xattrs, + xattr_count); + if (xattr_transmute) { + xattr_transmute->value = kmemdup(TRANS_TRUE, + TRANS_TRUE_SIZE, + GFP_NOFS); + if (!xattr_transmute->value) + return -ENOMEM; + + xattr_transmute->value_len = TRANS_TRUE_SIZE; + xattr_transmute->name = XATTR_SMACK_TRANSMUTE; + } } xattr->value = kstrdup(isp->smk_known, GFP_NOFS); @@ -3518,20 +3537,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * If there is a transmute attribute on the * directory mark the inode. */ - if (isp->smk_flags & SMK_INODE_CHANGED) { - isp->smk_flags &= ~SMK_INODE_CHANGED; - rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode, - XATTR_NAME_SMACKTRANSMUTE, - TRANS_TRUE, TRANS_TRUE_SIZE, - 0); - } else { - rc = __vfs_getxattr(dp, inode, - XATTR_NAME_SMACKTRANSMUTE, trattr, - TRANS_TRUE_SIZE); - if (rc >= 0 && strncmp(trattr, TRANS_TRUE, - TRANS_TRUE_SIZE) != 0) - rc = -EINVAL; - } + rc = __vfs_getxattr(dp, inode, + XATTR_NAME_SMACKTRANSMUTE, trattr, + TRANS_TRUE_SIZE); + if (rc >= 0 && strncmp(trattr, TRANS_TRUE, + TRANS_TRUE_SIZE) != 0) + rc = -EINVAL; if (rc >= 0) transflag = SMK_INODE_TRANSMUTE; } From patchwork Sat Jun 10 07:57:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13274763 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3986BBA20 for ; Sat, 10 Jun 2023 07:59:08 +0000 (UTC) Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2D31E3A86; Sat, 10 Jun 2023 00:59:02 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4QdVQY13Jdz9xFrN; Sat, 10 Jun 2023 15:47:01 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBH0AsGLYRklC8oAw--.4566S5; Sat, 10 Jun 2023 08:58:36 +0100 (CET) From: Roberto Sassu To: zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, stephen.smalley.work@gmail.com, eparis@parisplace.org, casey@schaufler-ca.com Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org, bpf@vger.kernel.org, kpsingh@kernel.org, keescook@chromium.org, nicolas.bouchinet@clip-os.org, Roberto Sassu Subject: [PATCH v12 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Date: Sat, 10 Jun 2023 09:57:37 +0200 Message-Id: <20230610075738.3273764-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> References: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBH0AsGLYRklC8oAw--.4566S5 X-Coremail-Antispam: 1UD129KBjvJXoWxXF43tw1kKw15Kr1kur48WFg_yoWrCF1xpF Zxt3WUCr1rJFyUWryFyF47u3WSgFWrGr4Dt393G34jyF1Dtr1xtFW0yr15uryrXrW8JrnY qw429r1rWwn0y3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUB2b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxAIw28IcxkI7V AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFYFCUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4qCJAABse X-CFilter-Loop: Reflected X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KHOP_HELO_FCRDNS, MAY_BE_FORGED,PDS_RDNS_DYNAMIC_FP,RDNS_DYNAMIC,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Roberto Sassu Change the evm_inode_init_security() definition to align with the LSM infrastructure. Keep the existing behavior of including in the HMAC calculation only the first xattr provided by LSMs. Changing the evm_inode_init_security() definition requires passing the xattr array allocated by security_inode_init_security(), and the number of xattrs filled by previously invoked LSMs. Use the newly introduced lsm_get_xattr_slot() to position EVM correctly in the xattrs array, like a regular LSM, and to increment the number of filled slots. For now, the LSM infrastructure allocates enough xattrs slots to store the EVM xattr, without using the reservation mechanism. Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar --- include/linux/evm.h | 14 ++++++++------ security/integrity/evm/evm_main.c | 16 ++++++++++------ security/security.c | 4 ++-- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/linux/evm.h b/include/linux/evm.h index 7dc1ee74169..01fc495a83e 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -56,9 +56,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, { return evm_inode_post_setxattr(dentry, acl_name, NULL, 0); } -extern int evm_inode_init_security(struct inode *inode, - const struct xattr *xattr_array, - struct xattr *evm); + +int evm_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, struct xattr *xattrs, + int *xattr_count); extern bool evm_revalidate_status(const char *xattr_name); extern int evm_protected_xattr_if_enabled(const char *req_xattr_name); extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, @@ -157,9 +158,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, return; } -static inline int evm_inode_init_security(struct inode *inode, - const struct xattr *xattr_array, - struct xattr *evm) +static inline int evm_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, + struct xattr *xattrs, + int *xattr_count) { return 0; } diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index cf24c525558..475196ce712 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -864,23 +865,26 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) /* * evm_inode_init_security - initializes security.evm HMAC value */ -int evm_inode_init_security(struct inode *inode, - const struct xattr *lsm_xattr, - struct xattr *evm_xattr) +int evm_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, struct xattr *xattrs, + int *xattr_count) { struct evm_xattr *xattr_data; + struct xattr *evm_xattr; int rc; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(lsm_xattr->name)) + if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs || + !evm_protected_xattr(xattrs->name)) return 0; + evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count); + xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); if (!xattr_data) return -ENOMEM; xattr_data->data.type = EVM_XATTR_HMAC; - rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); + rc = evm_init_hmac(inode, xattrs, xattr_data->digest); if (rc < 0) goto out; diff --git a/security/security.c b/security/security.c index d5ef7df1ce4..819294d91ad 100644 --- a/security/security.c +++ b/security/security.c @@ -1645,8 +1645,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (!xattr_count) goto out; - ret = evm_inode_init_security(inode, new_xattrs, - &new_xattrs[xattr_count]); + ret = evm_inode_init_security(inode, dir, qstr, new_xattrs, + &xattr_count); if (ret) goto out; ret = initxattrs(inode, new_xattrs, fs_data); From patchwork Sat Jun 10 07:57:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13274764 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A47F0BA20 for ; Sat, 10 Jun 2023 07:59:16 +0000 (UTC) Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 014CE3C06; Sat, 10 Jun 2023 00:59:07 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4QdVSN4Z3gz9xqd1; Sat, 10 Jun 2023 15:48:36 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBH0AsGLYRklC8oAw--.4566S6; Sat, 10 Jun 2023 08:58:45 +0100 (CET) From: Roberto Sassu To: zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, stephen.smalley.work@gmail.com, eparis@parisplace.org, casey@schaufler-ca.com Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org, bpf@vger.kernel.org, kpsingh@kernel.org, keescook@chromium.org, nicolas.bouchinet@clip-os.org, Roberto Sassu Subject: [PATCH v12 4/4] evm: Support multiple LSMs providing an xattr Date: Sat, 10 Jun 2023 09:57:38 +0200 Message-Id: <20230610075738.3273764-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> References: <20230610075738.3273764-1-roberto.sassu@huaweicloud.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBH0AsGLYRklC8oAw--.4566S6 X-Coremail-Antispam: 1UD129KBjvJXoWxGryktFy8JF1rur1rGr1kGrg_yoWrKrWDpa 98tas8Crn5JFy7Wr9aya18ua4SgrW8Cw1UK393JryjyFnIqr1IvryIyr15ur90grW8JrnI yw4Yvw15C3W5t3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBSb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxAIw28Icx kI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2Iq xVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAI cVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4A2js IEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj45+ZAAAsk X-CFilter-Loop: Reflected X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,KHOP_HELO_FCRDNS, MAY_BE_FORGED,PDS_RDNS_DYNAMIC_FP,RDNS_DYNAMIC,SPF_HELO_NONE,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net From: Roberto Sassu Currently, evm_inode_init_security() processes a single LSM xattr from the array passed by security_inode_init_security(), and calculates the HMAC on it and other inode metadata. As the LSM infrastructure now can pass to EVM an array with multiple xattrs, scan them until the terminator (xattr name NULL), and calculate the HMAC on all of them. Also, double check that the xattrs array terminator is the first non-filled slot (obtained with lsm_get_xattr_slot()). Consumers of the xattrs array, such as the initxattrs() callbacks, rely on the terminator. Finally, change the name of the lsm_xattr parameter of evm_init_hmac() to xattrs, to reflect the new type of information passed. Signed-off-by: Roberto Sassu Reviewed-by: Mimi Zohar Acked-by: Mimi Zohar --- security/integrity/evm/evm.h | 4 +++- security/integrity/evm/evm_crypto.c | 11 +++++++++-- security/integrity/evm/evm_main.c | 29 +++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index f8b8c5004fc..53bd7fec93f 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -46,6 +46,8 @@ struct evm_digest { char digest[IMA_MAX_DIGEST_SIZE]; } __packed; +int evm_protected_xattr(const char *req_xattr_name); + int evm_init_key(void); int evm_update_evmxattr(struct dentry *dentry, const char *req_xattr_name, @@ -58,7 +60,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, char type, struct evm_digest *data); -int evm_init_hmac(struct inode *inode, const struct xattr *xattr, +int evm_init_hmac(struct inode *inode, const struct xattr *xattrs, char *hmac_val); int evm_init_secfs(void); diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 033804f5a5f..eb6b9f0a5e9 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -385,10 +385,11 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, return rc; } -int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, +int evm_init_hmac(struct inode *inode, const struct xattr *xattrs, char *hmac_val) { struct shash_desc *desc; + const struct xattr *xattr; desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); if (IS_ERR(desc)) { @@ -396,7 +397,13 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, return PTR_ERR(desc); } - crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len); + for (xattr = xattrs; xattr->name; xattr++) { + if (!evm_protected_xattr(xattr->name)) + continue; + + crypto_shash_update(desc, xattr->value, xattr->value_len); + } + hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val); kfree(desc); return 0; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 475196ce712..7c6c9064ff5 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -306,7 +306,7 @@ static int evm_protected_xattr_common(const char *req_xattr_name, return found; } -static int evm_protected_xattr(const char *req_xattr_name) +int evm_protected_xattr(const char *req_xattr_name) { return evm_protected_xattr_common(req_xattr_name, false); } @@ -870,14 +870,35 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir, int *xattr_count) { struct evm_xattr *xattr_data; - struct xattr *evm_xattr; + struct xattr *xattr, *evm_xattr; + bool evm_protected_xattrs = false; int rc; - if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs || - !evm_protected_xattr(xattrs->name)) + if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs) + return 0; + + /* + * security_inode_init_security() makes sure that the xattrs array is + * contiguous, there is enough space for security.evm, and that there is + * a terminator at the end of the array. + */ + for (xattr = xattrs; xattr->name; xattr++) { + if (evm_protected_xattr(xattr->name)) + evm_protected_xattrs = true; + } + + /* EVM xattr not needed. */ + if (!evm_protected_xattrs) return 0; evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count); + /* + * Array terminator (xattr name = NULL) must be the first non-filled + * xattr slot. + */ + WARN_ONCE(evm_xattr != xattr, + "%s: xattrs terminator is not the first non-filled slot\n", + __func__); xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); if (!xattr_data)