From patchwork Wed Apr 21 16:19:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216447 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 576BCC43462 for ; Wed, 21 Apr 2021 16:20:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 20F326144D for ; Wed, 21 Apr 2021 16:20:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244268AbhDUQUl (ORCPT ); Wed, 21 Apr 2021 12:20:41 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2895 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241179AbhDUQUi (ORCPT ); Wed, 21 Apr 2021 12:20:38 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.206]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQYl6JSsz68Bmv; Thu, 22 Apr 2021 00:12:27 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:19:58 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu , , Jeff Mahoney , Tetsuo Handa Subject: [PATCH v2 1/6] xattr: Complete constify ->name member of "struct xattr" Date: Wed, 21 Apr 2021 18:19:20 +0200 Message-ID: <20210421161925.968825-2-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) 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 reiserfs_security_free(). Fixes: 9548906b2bb7 ('xattr: Constify ->name member of "struct xattr"') Cc: stable@vger.kernel.org Cc: Jeff Mahoney 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 Wed Apr 21 16:19:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216451 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 B2CE8C43617 for ; Wed, 21 Apr 2021 16:20:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 72B1761168 for ; Wed, 21 Apr 2021 16:20:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244246AbhDUQUp (ORCPT ); Wed, 21 Apr 2021 12:20:45 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2897 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244252AbhDUQUi (ORCPT ); Wed, 21 Apr 2021 12:20:38 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.200]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQVf0PPBz6wjBw; Thu, 22 Apr 2021 00:09:46 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:19:59 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu , , Jeff Mahoney , Tetsuo Handa Subject: [PATCH v2 2/6] reiserfs: Add missing calls to reiserfs_security_free() Date: Wed, 21 Apr 2021 18:19:21 +0200 Message-ID: <20210421161925.968825-3-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Commit 57fe60df6241 ("reiserfs: add atomic addition of selinux attributes during inode creation") defined reiserfs_security_free() to free the name and value of a security xattr allocated by the active LSM through security_old_inode_init_security(). However, this function is not called in the reiserfs code. Thus, this patch adds a call to reiserfs_security_free() whenever reiserfs_security_init() is called, and initializes value to NULL, to avoid to call kfree() on an uninitialized pointer. Fixes: 57fe60df6241 ("reiserfs: add atomic addition of selinux attributes during inode creation") Cc: stable@vger.kernel.org Cc: Jeff Mahoney Cc: Tetsuo Handa Reported-by: Mimi Zohar Reported-by: Tetsuo Handa Signed-off-by: Roberto Sassu --- fs/reiserfs/namei.c | 4 ++++ fs/reiserfs/xattr_security.c | 1 + 2 files changed, 5 insertions(+) diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index e6eb05e2b2f1..6b5c51a77fae 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -695,6 +695,7 @@ static int reiserfs_create(struct user_namespace *mnt_userns, struct inode *dir, out_failed: reiserfs_write_unlock(dir->i_sb); + reiserfs_security_free(&security); return retval; } @@ -778,6 +779,7 @@ static int reiserfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, out_failed: reiserfs_write_unlock(dir->i_sb); + reiserfs_security_free(&security); return retval; } @@ -877,6 +879,7 @@ static int reiserfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, retval = journal_end(&th); out_failed: reiserfs_write_unlock(dir->i_sb); + reiserfs_security_free(&security); return retval; } @@ -1193,6 +1196,7 @@ static int reiserfs_symlink(struct user_namespace *mnt_userns, retval = journal_end(&th); out_failed: reiserfs_write_unlock(parent_dir->i_sb); + reiserfs_security_free(&security); return retval; } diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index bb2a0062e0e5..b1ad93b60475 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -50,6 +50,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode, int error; sec->name = NULL; + sec->value = NULL; /* Don't add selinux attributes on xattrs - they'll never get used */ if (IS_PRIVATE(dir)) From patchwork Wed Apr 21 16:19:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216449 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 B1F11C43461 for ; Wed, 21 Apr 2021 16:20:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7A5176144E for ; Wed, 21 Apr 2021 16:20:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244274AbhDUQUm (ORCPT ); Wed, 21 Apr 2021 12:20:42 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2898 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244254AbhDUQUi (ORCPT ); Wed, 21 Apr 2021 12:20:38 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.226]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQc91b4hz6wjrk; Thu, 22 Apr 2021 00:14:33 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:20:00 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH v2 3/6] security: Pass xattrs allocated by LSMs to the inode_init_security hook Date: Wed, 21 Apr 2021 18:19:22 +0200 Message-ID: <20210421161925.968825-4-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) 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 replaces the name, value, len triple with the xattr array pointer provided by security_inode_init_security(). LSMs are expected to call the new function lsm_find_xattr_slot() to find the first unused slot of the array where the xattr should be written. This patch modifies also SELinux and Smack to search for an unused slot, to have a consistent behavior across LSMs (the unmodified version would overwrite the xattr set by the first LSM in the chain). It is also desirable to have the modification in those LSMs, as they are likely used as a reference for the development of new LSMs. Signed-off-by: Roberto Sassu --- include/linux/lsm_hook_defs.h | 4 ++-- include/linux/lsm_hooks.h | 18 +++++++++++++++--- security/security.c | 13 +++++++------ security/selinux/hooks.c | 13 ++++++------- security/smack/smack_lsm.c | 20 +++++++++----------- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 477a597db013..afb9dd122f60 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -111,8 +111,8 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask, 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) + struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, + void *fs_data) 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..e8c9bac29b9d 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -27,6 +27,7 @@ #include #include +#include #include /** @@ -227,9 +228,11 @@ * @inode contains the inode structure of the newly created inode. * @dir contains the inode structure of the parent directory. * @qstr contains the last path component of the new object - * @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. + * @xattrs contains the full array of xattrs allocated by LSMs where + * ->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. + * @fs_data contains filesystem-specific data. * Returns 0 if @name and @value have been successfully set, * -EOPNOTSUPP if no security attribute is needed, or * -ENOMEM on memory allocation failure. @@ -1661,4 +1664,13 @@ static inline void security_delete_hooks(struct security_hook_list *hooks, extern int lsm_inode_alloc(struct inode *inode); +static inline struct xattr *lsm_find_xattr_slot(struct xattr *xattrs) +{ + struct xattr *slot; + + for (slot = xattrs; slot && slot->name != NULL; slot++) + ; + + return slot; +} #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/security/security.c b/security/security.c index 7f14e59c4f8e..2c1fe1496069 100644 --- a/security/security.c +++ b/security/security.c @@ -1037,18 +1037,16 @@ 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, fs_data); 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); + lsm_xattr, fs_data); if (ret) 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, evm_xattr); if (ret) goto out; ret = initxattrs(inode, new_xattrs, fs_data); @@ -1071,10 +1069,13 @@ 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 xattr xattr = { .name = NULL, .value = NULL, .value_len = 0 }; + struct xattr *lsm_xattr = (name && value && len) ? &xattr : NULL; + if (unlikely(IS_PRIVATE(inode))) return -EOPNOTSUPP; return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, - qstr, name, value, len); + qstr, lsm_xattr, NULL); } EXPORT_SYMBOL(security_old_inode_init_security); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ddd097790d47..806827eb132a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2916,11 +2916,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, void *fs_data) { const struct task_security_struct *tsec = selinux_cred(current_cred()); struct superblock_security_struct *sbsec; + struct xattr *xattr = lsm_find_xattr_slot(xattrs); u32 newsid, clen; int rc; char *context; @@ -2947,16 +2947,15 @@ 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 (xattr) { + xattr->name = XATTR_SELINUX_SUFFIX; - if (value && len) { rc = security_sid_to_context_force(&selinux_state, newsid, &context, &clen); if (rc) return rc; - *value = context; - *len = clen; + xattr->value = context; + xattr->value_len = clen; } return 0; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 12a45e61c1a5..af7eee0fee52 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -962,26 +962,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 attribute * * 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, void *fs_data) { struct inode_smack *issp = smack_inode(inode); struct smack_known *skp = smk_of_current(); struct smack_known *isp = smk_of_inode(inode); struct smack_known *dsp = smk_of_inode(dir); + struct xattr *xattr = lsm_find_xattr_slot(xattrs); int may; - if (name) - *name = XATTR_SMACK_SUFFIX; + if (xattr) { + xattr->name = XATTR_SMACK_SUFFIX; - if (value && len) { rcu_read_lock(); may = smk_access_entry(skp->smk_known, dsp->smk_known, &skp->smk_rules); @@ -999,11 +997,11 @@ 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 == NULL) return -ENOMEM; - *len = strlen(isp->smk_known); + xattr->value_len = strlen(isp->smk_known); } return 0; From patchwork Wed Apr 21 16:19:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216453 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 C3DC5C43618 for ; Wed, 21 Apr 2021 16:20:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 90AE861459 for ; Wed, 21 Apr 2021 16:20:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244290AbhDUQUp (ORCPT ); Wed, 21 Apr 2021 12:20:45 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2899 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244256AbhDUQUi (ORCPT ); Wed, 21 Apr 2021 12:20:38 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQVg2LKKz6wjbk; Thu, 22 Apr 2021 00:09:47 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:20:00 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH v2 4/6] security: Support multiple LSMs implementing the inode_init_security hook Date: Wed, 21 Apr 2021 18:19:23 +0200 Message-ID: <20210421161925.968825-5-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) 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). 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 | 93 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/security/security.c b/security/security.c index 2c1fe1496069..2ab67fa4422e 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 *new_xattrs; struct xattr *lsm_xattr, *evm_xattr, *xattr; - int ret; + struct security_hook_list *P; + int ret, max_new_xattrs = 0; if (unlikely(IS_PRIVATE(inode))) return 0; @@ -1038,14 +1037,52 @@ 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, fs_data); - 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, fs_data); - if (ret) + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, + list) { + ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs, + fs_data); + if (ret) { + if (ret != -EOPNOTSUPP) + goto out; + + continue; + } + + /* LSM implementation error. */ + if (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; + } + + lsm_xattr++; + + if (!--max_new_xattrs) + break; + } + + if (!new_xattrs->name) { + ret = -EOPNOTSUPP; goto out; + } - evm_xattr = lsm_xattr + 1; + evm_xattr = lsm_xattr; ret = evm_inode_init_security(inode, new_xattrs, evm_xattr); if (ret) goto out; @@ -1053,6 +1090,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, 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,11 +1109,44 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, { struct xattr xattr = { .name = NULL, .value = NULL, .value_len = 0 }; struct xattr *lsm_xattr = (name && value && len) ? &xattr : NULL; + 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, lsm_xattr, NULL); + + hlist_for_each_entry(P, &security_hook_heads.inode_init_security, + list) { + ret = P->hook.inode_init_security(inode, dir, qstr, lsm_xattr, + NULL); + if (ret) { + if (ret != -EOPNOTSUPP) + return ret; + + continue; + } + + if (!lsm_xattr) + continue; + + /* LSM implementation error. */ + if (lsm_xattr->name == NULL || lsm_xattr->value == NULL) { + WARN_ONCE( + "LSM %s: ret = 0 but xattr name/value = NULL\n", + P->lsm); + + /* Callers should do the cleanup. */ + return -ENOENT; + } + + *name = lsm_xattr->name; + *value = lsm_xattr->value; + *len = lsm_xattr->value_len; + + return ret; + } + + return -EOPNOTSUPP; } EXPORT_SYMBOL(security_old_inode_init_security); From patchwork Wed Apr 21 16:19:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216457 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 1A6D2C43461 for ; Wed, 21 Apr 2021 16:21:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D429561454 for ; Wed, 21 Apr 2021 16:21:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242283AbhDUQV4 (ORCPT ); Wed, 21 Apr 2021 12:21:56 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2900 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242053AbhDUQVz (ORCPT ); Wed, 21 Apr 2021 12:21:55 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.226]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQX96l34z6wjBw; Thu, 22 Apr 2021 00:11:05 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:21:19 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH v2 5/6] evm: Align evm_inode_init_security() definition with LSM infrastructure Date: Wed, 21 Apr 2021 18:19:24 +0200 Message-ID: <20210421161925.968825-6-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) 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 | 17 ++++++++++------- security/integrity/evm/evm_main.c | 17 +++++++++++------ security/security.c | 7 +++---- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/linux/evm.h b/include/linux/evm.h index 8cad46bcec9d..b6c4092426f3 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -34,9 +34,9 @@ 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, + struct xattr *xattrs, void *fs_data); extern bool evm_status_revalidate(const char *xattr_name); #ifdef CONFIG_FS_POSIX_ACL extern int posix_xattr_acl(const char *xattrname); @@ -102,11 +102,14 @@ 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, + struct xattr *xattrs, void *fs_data) { - return 0; + if (!xattrs || !xattrs->name) + 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..336a421e2e5a 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -706,23 +707,27 @@ 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, void *fs_data) { struct evm_xattr *xattr_data; + struct xattr *evm_xattr = lsm_find_xattr_slot(xattrs); int rc; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(lsm_xattr->name)) + if (!xattrs || !xattrs->name) return 0; + if (!(evm_initialized & EVM_INIT_HMAC) || + !evm_protected_xattr(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, xattrs, xattr_data->digest); if (rc < 0) goto out; diff --git a/security/security.c b/security/security.c index 2ab67fa4422e..ee5b9caccc40 100644 --- a/security/security.c +++ b/security/security.c @@ -1027,7 +1027,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, const initxattrs initxattrs, void *fs_data) { struct xattr *new_xattrs; - struct xattr *lsm_xattr, *evm_xattr, *xattr; + struct xattr *lsm_xattr, *xattr; struct security_hook_list *P; int ret, max_new_xattrs = 0; @@ -1082,9 +1082,8 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, goto out; } - evm_xattr = lsm_xattr; - ret = evm_inode_init_security(inode, new_xattrs, evm_xattr); - if (ret) + ret = evm_inode_init_security(inode, dir, qstr, new_xattrs, fs_data); + if (ret && ret != -EOPNOTSUPP) goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: From patchwork Wed Apr 21 16:19:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12216455 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 53CACC43460 for ; Wed, 21 Apr 2021 16:21:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 21C806144B for ; Wed, 21 Apr 2021 16:21:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242409AbhDUQV4 (ORCPT ); Wed, 21 Apr 2021 12:21:56 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:2901 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242271AbhDUQVz (ORCPT ); Wed, 21 Apr 2021 12:21:55 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.201]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4FQQdj1qVPz6yh4l; Thu, 22 Apr 2021 00:15:53 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.62.217) 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.2176.2; Wed, 21 Apr 2021 18:21:20 +0200 From: Roberto Sassu To: , , , CC: , , , , , Roberto Sassu Subject: [PATCH v2 6/6] evm: Support multiple LSMs providing an xattr Date: Wed, 21 Apr 2021 18:19:25 +0200 Message-ID: <20210421161925.968825-7-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210421161925.968825-1-roberto.sassu@huawei.com> References: <20210421161925.968825-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.217] X-ClientProxiedBy: lhreml754-chm.china.huawei.com (10.201.108.204) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: 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. 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 336a421e2e5a..c43e75cd37f3 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -261,7 +261,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, struct xattr *xattrs, void *fs_data) { struct evm_xattr *xattr_data; + struct xattr *xattr; struct xattr *evm_xattr = lsm_find_xattr_slot(xattrs); - int rc; + int rc, evm_protected_xattrs = 0; if (!xattrs || !xattrs->name) return 0; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(xattrs->name)) + if (!(evm_initialized & EVM_INIT_HMAC)) + return -EOPNOTSUPP; + + for (xattr = xattrs; 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);