From patchwork Thu Apr 15 10:04:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12204919 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0A513C43462 for ; Thu, 15 Apr 2021 10:04:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3054613B1 for ; Thu, 15 Apr 2021 10:04:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232071AbhDOKFP (ORCPT ); Thu, 15 Apr 2021 06:05:15 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2861 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230190AbhDOKFO (ORCPT ); Thu, 15 Apr 2021 06:05:14 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FLZZC5H9Fz68BJf; Thu, 15 Apr 2021 17:59:31 +0800 (CST) Received: from fraphisprd00473.huawei.com (7.182.8.141) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 12:04:49 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu , , Tetsuo Handa Subject: [PATCH 1/5] xattr: Complete constify ->name member of "struct xattr" Date: Thu, 15 Apr 2021 12:04:31 +0200 Message-ID: <20210415100435.18619-2-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210415100435.18619-1-roberto.sassu@huawei.com> References: <20210415100435.18619-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [7.182.8.141] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: This patch completes commit 9548906b2bb7 ('xattr: Constify ->name member of "struct xattr"'). It fixes the documentation of the inode_init_security hook, by removing the xattr name from the objects that are expected to be allocated by LSMs (only the value is allocated). Also, it removes the kfree() of name and setting it to NULL in the reiserfs code. Fixes: 9548906b2bb7 ('xattr: Constify ->name member of "struct xattr"') Cc: stable@vger.kernel.org Cc: Tetsuo Handa Signed-off-by: Roberto Sassu --- fs/reiserfs/xattr_security.c | 2 -- include/linux/lsm_hooks.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 8965c8e5e172..bb2a0062e0e5 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -95,9 +95,7 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th, void reiserfs_security_free(struct reiserfs_security_handle *sec) { - kfree(sec->name); kfree(sec->value); - sec->name = NULL; sec->value = NULL; } diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index fb7f3193753d..c5498f5174ce 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -219,8 +219,8 @@ * 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. + * is expected to allocate the value via kmalloc, with the caller + * being responsible for calling kfree after using it. * 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. From patchwork Thu Apr 15 10:04:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12204921 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E255C43600 for ; Thu, 15 Apr 2021 10:04:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DAFB611AD for ; Thu, 15 Apr 2021 10:04:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232138AbhDOKFQ (ORCPT ); Thu, 15 Apr 2021 06:05:16 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2862 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230260AbhDOKFP (ORCPT ); Thu, 15 Apr 2021 06:05:15 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.200]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FLZSv5lTgz689dF; Thu, 15 Apr 2021 17:54:55 +0800 (CST) Received: from fraphisprd00473.huawei.com (7.182.8.141) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 12:04:50 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH 2/5] security: Support multiple LSMs implementing the inode_init_security hook Date: Thu, 15 Apr 2021 12:04:32 +0200 Message-ID: <20210415100435.18619-3-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210415100435.18619-1-roberto.sassu@huawei.com> References: <20210415100435.18619-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [7.182.8.141] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: The current implementation of security_inode_init_security() is capable of handling only one LSM providing an xattr to be set at inode creation. That xattr is then passed to EVM to calculate the HMAC. To support multiple LSMs, each providing an xattr, this patch makes the following modifications: security_inode_init_security(): - dynamically allocates new_xattrs, based on the number of inode_init_security hooks registered by LSMs; - replaces the call_int_hook() macro with its definition, to correctly handle the case of an LSM returning -EOPNOTSUPP (the loop should not be stopped), and to advance in the new_xattrs array so that the correct xattr name, value and len pointers are passed to LSMs. security_old_inode_init_security(): - replaces the call_int_hook() macro with its definition, to stop the loop at the first LSM providing an xattr, to avoid a memory leak (due to overwriting the *value pointer). The modifications necessary for EVM to calculate the HMAC on all xattrs will be done in a separate patch. Signed-off-by: Roberto Sassu --- security/security.c | 87 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/security/security.c b/security/security.c index 7f14e59c4f8e..65624357b335 100644 --- a/security/security.c +++ b/security/security.c @@ -30,8 +30,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) @@ -1028,9 +1026,10 @@ 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 xattr *new_xattrs; + struct xattr *lsm_xattr, *xattr; + struct security_hook_list *P; + int ret, max_new_xattrs = 0; if (unlikely(IS_PRIVATE(inode))) return 0; @@ -1038,23 +1037,56 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (!initxattrs) return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr, NULL, NULL, NULL); - memset(new_xattrs, 0, sizeof(new_xattrs)); + + /* Determine at run-time the max number of xattr structs to allocate. */ + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, list) + max_new_xattrs++; + + if (!max_new_xattrs) + return 0; + + /* Allocate +1 for EVM and +1 as terminator. */ + new_xattrs = kcalloc(max_new_xattrs + 2, sizeof(*new_xattrs), GFP_NOFS); + if (!new_xattrs) + return -ENOMEM; + 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) + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, + list) { + ret = P->hook.inode_init_security(inode, dir, qstr, + &lsm_xattr->name, + &lsm_xattr->value, + &lsm_xattr->value_len); + if (ret && ret != -EOPNOTSUPP) + goto out; + + /* LSM implementation error. */ + if (!ret && + (lsm_xattr->name == NULL || lsm_xattr->value == NULL)) { + WARN_ONCE( + "LSM %s: ret = 0 but xattr name/value = NULL\n", + P->lsm); + ret = -ENOENT; + goto out; + } + + if (!ret && lsm_xattr < new_xattrs + max_new_xattrs) + lsm_xattr++; + } + + if (lsm_xattr == new_xattrs) { + ret = -EOPNOTSUPP; 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, lsm_xattr); if (ret) goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: for (xattr = new_xattrs; xattr->value != NULL; xattr++) kfree(xattr->value); + kfree(new_xattrs); return (ret == -EOPNOTSUPP) ? 0 : ret; } EXPORT_SYMBOL(security_inode_init_security); @@ -1071,10 +1103,35 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len) { + struct security_hook_list *P; + int ret; + if (unlikely(IS_PRIVATE(inode))) return -EOPNOTSUPP; - return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, - qstr, name, value, len); + + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, + list) { + ret = P->hook.inode_init_security(inode, dir, qstr, + name, value, len); + if (ret && ret != -EOPNOTSUPP) + return ret; + + /* LSM implementation error. */ + if (!ret && + ((name && *name == NULL) || (value && *value == NULL))) { + WARN_ONCE( + "LSM %s: ret = 0 but xattr name/value = NULL\n", + P->lsm); + + /* Callers should do the cleanup. */ + return -ENOENT; + } + + if (!ret) + return ret; + } + + return -EOPNOTSUPP; } EXPORT_SYMBOL(security_old_inode_init_security); From patchwork Thu Apr 15 10:04:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12204923 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B030EC43461 for ; Thu, 15 Apr 2021 10:04:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8D10561249 for ; Thu, 15 Apr 2021 10:04:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232173AbhDOKFS (ORCPT ); Thu, 15 Apr 2021 06:05:18 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2863 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230526AbhDOKFP (ORCPT ); Thu, 15 Apr 2021 06:05:15 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.201]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FLZSw2vvJz689d5; Thu, 15 Apr 2021 17:54:56 +0800 (CST) Received: from fraphisprd00473.huawei.com (7.182.8.141) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 12:04:50 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH 3/5] security: Pass xattrs allocated by LSMs to the inode_init_security hook Date: Thu, 15 Apr 2021 12:04:33 +0200 Message-ID: <20210415100435.18619-4-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210415100435.18619-1-roberto.sassu@huawei.com> References: <20210415100435.18619-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [7.182.8.141] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: In preparation for moving EVM to the LSM infrastructure, this patch adds the full array of xattrs allocated by LSMs as a new parameter of the inode_init_security hook. It will be used by EVM to calculate the HMAC on all xattrs. This solution has been preferred to directly replacing the xattr name, value and len with the full array, as LSMs would have had to scan it to find an empty slot. Signed-off-by: Roberto Sassu --- include/linux/lsm_hook_defs.h | 2 +- include/linux/lsm_hooks.h | 1 + security/security.c | 7 ++++--- security/selinux/hooks.c | 3 ++- security/smack/smack_lsm.c | 4 +++- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 477a597db013..45a0b8cbb974 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -112,7 +112,7 @@ 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) + void **value, size_t *len, struct xattr *lsm_xattrs) 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 c5498f5174ce..1dd79e2f02ad 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -230,6 +230,7 @@ * @name will be set to the allocated name suffix (e.g. selinux). * @value will be set to the allocated attribute value. * @len will be set to the length of the value. + * @lsm_xattrs contains the full array of xattrs allocated by LSMs. * Returns 0 if @name and @value have been successfully set, * -EOPNOTSUPP if no security attribute is needed, or * -ENOMEM on memory allocation failure. diff --git a/security/security.c b/security/security.c index 65624357b335..8aabbc0f0dfc 100644 --- a/security/security.c +++ b/security/security.c @@ -1036,7 +1036,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (!initxattrs) return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, - dir, qstr, NULL, NULL, NULL); + dir, qstr, NULL, NULL, NULL, NULL); /* Determine at run-time the max number of xattr structs to allocate. */ hlist_for_each_entry(P, &security_hook_heads.inode_init_security, list) @@ -1056,7 +1056,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, ret = P->hook.inode_init_security(inode, dir, qstr, &lsm_xattr->name, &lsm_xattr->value, - &lsm_xattr->value_len); + &lsm_xattr->value_len, + new_xattrs); if (ret && ret != -EOPNOTSUPP) goto out; @@ -1112,7 +1113,7 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, hlist_for_each_entry(P, &security_hook_heads.inode_init_security, list) { ret = P->hook.inode_init_security(inode, dir, qstr, - name, value, len); + name, value, len, NULL); if (ret && ret != -EOPNOTSUPP) return ret; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ddd097790d47..2fe9c39414d0 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2917,7 +2917,8 @@ 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) + void **value, size_t *len, + struct xattr *lsm_xattrs) { const struct task_security_struct *tsec = selinux_cred(current_cred()); struct superblock_security_struct *sbsec; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 12a45e61c1a5..9d562ea576ca 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -965,12 +965,14 @@ static int smack_inode_alloc_security(struct inode *inode) * @name: where to put the attribute name * @value: where to put the attribute value * @len: where to put the length of the attribute + * @lsm_xattrs: unused * * 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) + void **value, size_t *len, + struct xattr *lsm_xattrs) { struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_current(); From patchwork Thu Apr 15 10:04:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12204925 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D957C43460 for ; Thu, 15 Apr 2021 10:05:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7634A611AD for ; Thu, 15 Apr 2021 10:05:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232227AbhDOKFU (ORCPT ); Thu, 15 Apr 2021 06:05:20 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2864 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231919AbhDOKFQ (ORCPT ); Thu, 15 Apr 2021 06:05:16 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.226]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FLZZF44m0z68BH0; Thu, 15 Apr 2021 17:59:33 +0800 (CST) Received: from fraphisprd00473.huawei.com (7.182.8.141) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 12:04:51 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH 4/5] evm: Align evm_inode_init_security() definition with LSM infrastructure Date: Thu, 15 Apr 2021 12:04:34 +0200 Message-ID: <20210415100435.18619-5-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210415100435.18619-1-roberto.sassu@huawei.com> References: <20210415100435.18619-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [7.182.8.141] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: This patch changes the evm_inode_init_security() definition to align with the LSM infrastructure, in preparation for moving IMA and EVM to that infrastructure. Signed-off-by: Roberto Sassu --- include/linux/evm.h | 21 ++++++++++++++------- security/integrity/evm/evm_main.c | 24 +++++++++++++++--------- security/security.c | 7 +++++-- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/linux/evm.h b/include/linux/evm.h index 8cad46bcec9d..5d8b29d80296 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -34,9 +34,11 @@ extern int evm_inode_removexattr(struct user_namespace *mnt_userns, struct dentry *dentry, const char *xattr_name); extern void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name); -extern int evm_inode_init_security(struct inode *inode, - const struct xattr *xattr_array, - struct xattr *evm); +extern int evm_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, + const char **name, + void **value, size_t *len, + struct xattr *lsm_xattrs); extern bool evm_status_revalidate(const char *xattr_name); #ifdef CONFIG_FS_POSIX_ACL extern int posix_xattr_acl(const char *xattrname); @@ -102,11 +104,16 @@ static inline void evm_inode_post_removexattr(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, + const char **name, + void **value, size_t *len, + struct xattr *lsm_xattrs) { - return 0; + if (!name || !value || !len || !lsm_xattrs) + return 0; + + return -EOPNOTSUPP; } static inline bool evm_status_revalidate(const char *xattr_name) diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 84a9b7a69b1f..a5069d69a893 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -706,29 +706,35 @@ 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, + const char **name, + void **value, size_t *len, + struct xattr *lsm_xattrs) { struct evm_xattr *xattr_data; int rc; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(lsm_xattr->name)) + if (!name || !value || !len || !lsm_xattrs) return 0; + if (!(evm_initialized & EVM_INIT_HMAC) || + !evm_protected_xattr(lsm_xattrs->name)) + return -EOPNOTSUPP; + 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, lsm_xattrs, xattr_data->digest); if (rc < 0) goto out; - evm_xattr->value = xattr_data; - evm_xattr->value_len = hash_digest_size[evm_hash_algo] + 1; - evm_xattr->name = XATTR_EVM_SUFFIX; + *name = XATTR_EVM_SUFFIX; + *value = xattr_data; + *len = hash_digest_size[evm_hash_algo] + 1; + return 0; out: kfree(xattr_data); diff --git a/security/security.c b/security/security.c index 8aabbc0f0dfc..e16ce150b111 100644 --- a/security/security.c +++ b/security/security.c @@ -1080,8 +1080,11 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, goto out; } - ret = evm_inode_init_security(inode, new_xattrs, lsm_xattr); - if (ret) + ret = evm_inode_init_security(inode, dir, qstr, + &lsm_xattr->name, + &lsm_xattr->value, + &lsm_xattr->value_len, new_xattrs); + if (ret && ret != -EOPNOTSUPP) goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: From patchwork Thu Apr 15 10:04:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12204927 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D6B3C433B4 for ; Thu, 15 Apr 2021 10:06:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E46661249 for ; Thu, 15 Apr 2021 10:06:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232380AbhDOKG2 (ORCPT ); Thu, 15 Apr 2021 06:06:28 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2865 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232366AbhDOKG1 (ORCPT ); Thu, 15 Apr 2021 06:06:27 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.226]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FLZVJ3cf5z689tm; Thu, 15 Apr 2021 17:56:08 +0800 (CST) Received: from fraphisprd00473.huawei.com (7.182.8.141) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2106.2; Thu, 15 Apr 2021 12:06:02 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH 5/5] evm: Support multiple LSMs providing an xattr Date: Thu, 15 Apr 2021 12:04:35 +0200 Message-ID: <20210415100435.18619-6-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210415100435.18619-1-roberto.sassu@huawei.com> References: <20210415100435.18619-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [7.182.8.141] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Currently, evm_inode_init_security() takes as input a single LSM xattr, passed by security_inode_init_security(), and calculates the HMAC on it and other inode metadata. Given that initxattrs(), called by security_inode_init_security(), expects that this array is terminated when the xattr name is set to NULL, this patch reuses the same assumption for evm_inode_init_security() to scan all xattrs and to calculate the HMAC on all of them. Signed-off-by: Roberto Sassu --- security/integrity/evm/evm.h | 2 ++ security/integrity/evm/evm_crypto.c | 9 ++++++++- security/integrity/evm/evm_main.c | 15 +++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index ae590f71ce7d..24eac42b9f32 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -49,6 +49,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 __init evm_init_crypto(void); int evm_update_evmxattr(struct dentry *dentry, diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index b66264b53d5d..35c5eec0517d 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -358,6 +358,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, char *hmac_val) { struct shash_desc *desc; + const struct xattr *xattr; desc = init_desc(EVM_XATTR_HMAC, evm_hash_algo); if (IS_ERR(desc)) { @@ -365,7 +366,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 = lsm_xattr; xattr->name != NULL; 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 a5069d69a893..fde366149499 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -260,7 +260,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, return evm_status; } -static int evm_protected_xattr(const char *req_xattr_name) +int evm_protected_xattr(const char *req_xattr_name) { int namelen; int found = 0; @@ -712,14 +712,21 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir, void **value, size_t *len, struct xattr *lsm_xattrs) { + struct xattr *xattr; struct evm_xattr *xattr_data; - int rc; + int rc, evm_protected_xattrs = 0; if (!name || !value || !len || !lsm_xattrs) return 0; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(lsm_xattrs->name)) + if (!(evm_initialized & EVM_INIT_HMAC)) + return -EOPNOTSUPP; + + for (xattr = lsm_xattrs; xattr && xattr->name != NULL; xattr++) + if (evm_protected_xattr(xattr->name)) + evm_protected_xattrs++; + + if (!evm_protected_xattrs) return -EOPNOTSUPP; xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);