From patchwork Fri Dec 10 19:47:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670845 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E079DC433EF for ; Fri, 10 Dec 2021 19:48:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343761AbhLJTvi (ORCPT ); Fri, 10 Dec 2021 14:51:38 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:56842 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343713AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJRwi2021289; Fri, 10 Dec 2021 19:47:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=ByNF7ROf2DqzpRSnI/OPFdOK/GBjbR3Rry0Bm2YyfS4=; b=c664Y2CHdDoyHf6ppnbk83Rotzf9GE+qGh5AuMSVZDYNphETDwn9rlfd5z/tCSJ7GwrC dEW9ytGtEW0M5BRf9GO9vreHwHR2hED6eU+4KkzNcD47ss5S6oB757vrNEknuMD35DNw HgZnPr6bDm3e3IDCiLK4x/kSiwIdjuo0daDNNRzeTcwcc2z2Qz1XCHhJ6A3XIzJE3Haa r8zD3thAIVq67IAMwY3mjp3OjO/jI2+aGy6+yceBN5JDjiBIJ3hestiKo1N2lYE4/V3Y xxvhXXoLlwV+w0ZNpSYb1H+DB2Zg3WBYNiGBNYRdFByhkOR0j84M86CZt5Imhnoh3rFl tA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2u8b85-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from m0098416.ppops.net (m0098416.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJS8g4022468; Fri, 10 Dec 2021 19:47:40 GMT Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2u8b7u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJc5OU011559; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma01dal.us.ibm.com with ESMTP id 3cqyyekvye-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlc0L38207860 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EE56BAE05F; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CE5E8AE064; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , James Bottomley Subject: [PATCH v6 01/17] ima: Add IMA namespace support Date: Fri, 10 Dec 2021 14:47:20 -0500 Message-Id: <20211210194736.1538863-2-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: mylM2eX3m8H-pdfm51JFN-7h2fg12FKM X-Proofpoint-ORIG-GUID: IlFnzNf_-76I3AlAvrKPlkDfYYimp3XU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 suspectscore=0 phishscore=0 priorityscore=1501 spamscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 impostorscore=0 mlxlogscore=999 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Implement an IMA namespace data structure that gets created alongside a user namespace with CLONE_NEWUSER. This lays down the foundation for namespacing the different aspects of IMA (eg. IMA-audit, IMA-measurement, IMA-appraisal). Signed-off-by: Stefan Berger Suggested-by: James Bottomley --- include/linux/ima.h | 37 +++++++++++++ include/linux/user_namespace.h | 4 ++ init/Kconfig | 10 ++++ kernel/user.c | 7 +++ kernel/user_namespace.c | 8 +++ security/integrity/ima/Makefile | 3 +- security/integrity/ima/ima.h | 4 ++ security/integrity/ima/ima_init.c | 4 ++ security/integrity/ima/ima_init_ima_ns.c | 32 +++++++++++ security/integrity/ima/ima_ns.c | 69 ++++++++++++++++++++++++ 10 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 security/integrity/ima/ima_init_ima_ns.c create mode 100644 security/integrity/ima/ima_ns.c diff --git a/include/linux/ima.h b/include/linux/ima.h index b6ab66a546ae..f282e40c316c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -11,6 +11,7 @@ #include #include #include +#include #include struct linux_binprm; @@ -210,6 +211,42 @@ static inline int ima_inode_removexattr(struct dentry *dentry, } #endif /* CONFIG_IMA_APPRAISE */ +struct ima_namespace { + int avoid_zero_size; +}; + +extern struct ima_namespace init_ima_ns; + +#ifdef CONFIG_IMA_NS + +void free_ima_ns(struct user_namespace *ns); +int create_ima_ns(struct user_namespace *user_ns); + +static inline struct ima_namespace *get_current_ns(void) +{ + return current_user_ns()->ima_ns; +} + +#else + +static inline void free_ima_ns(struct user_namespace *user_ns) +{ +} + +static inline int create_ima_ns(struct user_namespace *user_ns) +{ +#ifdef CONFIG_IMA + user_ns->ima_ns = &init_ima_ns; +#endif + return 0; +} + +static inline struct ima_namespace *get_current_ns(void) +{ + return &init_ima_ns; +} +#endif /* CONFIG_IMA_NS */ + #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) extern bool ima_appraise_signature(enum kernel_read_file_id func); #else diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 33a4240e6a6f..5249db04d62b 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -36,6 +36,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED struct ucounts; +struct ima_namespace; enum ucount_type { UCOUNT_USER_NAMESPACES, @@ -99,6 +100,9 @@ struct user_namespace { #endif struct ucounts *ucounts; long ucount_max[UCOUNT_COUNTS]; +#ifdef CONFIG_IMA + struct ima_namespace *ima_ns; +#endif } __randomize_layout; struct ucounts { diff --git a/init/Kconfig b/init/Kconfig index 11f8a845f259..27890607e8cb 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1242,6 +1242,16 @@ config NET_NS Allow user space to create what appear to be multiple instances of the network stack. +config IMA_NS + bool "IMA namespace" + depends on USER_NS + depends on IMA + default y + help + Allow the creation of IMA namespaces for each user namespace. + Namespaced IMA enables having IMA features work separately + in each IMA namespace. + endif # NAMESPACES config CHECKPOINT_RESTORE diff --git a/kernel/user.c b/kernel/user.c index e2cf8c22b539..287751d89b44 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -20,6 +20,10 @@ #include #include +#ifdef CONFIG_IMA +extern struct ima_namespace init_ima_ns; +#endif + /* * userns count is 1 for root user, 1 for init_uts_ns, * and 1 for... ? @@ -67,6 +71,9 @@ struct user_namespace init_user_ns = { .keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list), .keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem), #endif +#ifdef CONFIG_IMA + .ima_ns = &init_ima_ns, +#endif }; EXPORT_SYMBOL_GPL(init_user_ns); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6b2e3ca7ee99..6fa01323aac9 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -20,6 +20,7 @@ #include #include #include +#include static struct kmem_cache *user_ns_cachep __read_mostly; static DEFINE_MUTEX(userns_state_mutex); @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) if (!setup_userns_sysctls(ns)) goto fail_keyring; + ret = create_ima_ns(ns); + if (ret) + goto fail_sysctls; + set_cred_user_ns(new, ns); return 0; +fail_sysctls: + retire_userns_sysctls(ns); fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); @@ -196,6 +203,7 @@ static void free_user_ns(struct work_struct *work) kfree(ns->projid_map.forward); kfree(ns->projid_map.reverse); } + free_ima_ns(ns); retire_userns_sysctls(ns); key_free_user_ns(ns); ns_free_inum(&ns->ns); diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 2499f2485c04..b86a35fbed60 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -7,13 +7,14 @@ obj-$(CONFIG_IMA) += ima.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ - ima_policy.o ima_template.o ima_template_lib.o + ima_policy.o ima_template.o ima_template_lib.o ima_init_ima_ns.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o +ima-$(CONFIG_IMA_NS) += ima_ns.o ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index be965a8715e4..2f8adf383054 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -418,6 +418,10 @@ static inline void ima_free_modsig(struct modsig *modsig) } #endif /* CONFIG_IMA_APPRAISE_MODSIG */ +int ima_ns_init(void); +struct ima_namespace; +int ima_init_namespace(struct ima_namespace *ns); + /* LSM based policy rules require audit */ #ifdef CONFIG_IMA_LSM_RULES diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b26fa67476b4..f6ae4557a0da 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -120,6 +120,10 @@ int __init ima_init(void) { int rc; + rc = ima_ns_init(); + if (rc) + return rc; + ima_tpm_chip = tpm_default_chip(); if (!ima_tpm_chip) pr_info("No TPM chip found, activating TPM-bypass!\n"); diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c new file mode 100644 index 000000000000..f820686baf9f --- /dev/null +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun + * Stefan Berger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include +#include +#include +#include + +#include "ima.h" + +int ima_init_namespace(struct ima_namespace *ns) +{ + return 0; +} + +int __init ima_ns_init(void) +{ + return ima_init_namespace(&init_ima_ns); +} + +struct ima_namespace init_ima_ns = { +}; +EXPORT_SYMBOL(init_ima_ns); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c new file mode 100644 index 000000000000..c575ddf0c3f3 --- /dev/null +++ b/security/integrity/ima/ima_ns.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun + * Stefan Berger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "ima.h" + +static struct kmem_cache *imans_cachep; + +int create_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns; + int err; + + ns = kmem_cache_zalloc(imans_cachep, GFP_KERNEL); + if (!ns) + return -ENOMEM; + pr_debug("NEW ima_ns: 0x%p\n", ns); + + err = ima_init_namespace(ns); + if (err) + goto fail_free; + + user_ns->ima_ns = ns; + + return 0; + +fail_free: + kmem_cache_free(imans_cachep, ns); + + return err; +} + +static void destroy_ima_ns(struct ima_namespace *ns) +{ + pr_debug("DESTROY ima_ns: 0x%p\n", ns); + kmem_cache_free(imans_cachep, ns); +} + +void free_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns = user_ns->ima_ns; + + if (WARN_ON(ns == &init_ima_ns)) + return; + + destroy_ima_ns(ns); +} + +static int __init imans_cache_init(void) +{ + imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); + return 0; +} +subsys_initcall(imans_cache_init) From patchwork Fri Dec 10 19:47:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670813 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3033C433F5 for ; Fri, 10 Dec 2021 19:47:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242388AbhLJTv1 (ORCPT ); Fri, 10 Dec 2021 14:51:27 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:38306 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S236525AbhLJTv0 (ORCPT ); Fri, 10 Dec 2021 14:51:26 -0500 Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAIvoQu030646; Fri, 10 Dec 2021 19:47:40 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=aYU0Blv4LRazBo9rZ0qR9tRJCzKhTaAbtSfvRFyJWdI=; b=J1upG8dLzD4mtXTSUlTCBeKZeUA7JNufyI8UhQqsnOpSTBOZfqqDtnL8oVxL7OKbNgOc MH2dN+NwZ3bXAD7bwVbt/e8pf2WkTPI9DYfXOZao/Rk3+4N/wgpaIc5sesaniTZ/Jvy+ d9Ahs9HmnWnUj+sO7FbHkZ7GPJFOMWdRyXKVFnXv8PHpiGtVdMKdjCBSwScpQIiDZQNz Yu4I+PApwvH2tzG60oepUnPzHPe3kdt6/4WZCTOQ9I/0TBzPaKMCEJDMOCDnDRrL/v4F OwvWdSJpVwFsdHXpCa0aCbiDhfeQqZmOu9n66KE83VwNYotDXNIX4FZmdecZqELDqxlC 8w== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvcms903e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from m0098419.ppops.net (m0098419.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJjUes022778; Fri, 10 Dec 2021 19:47:39 GMT Received: from ppma04wdc.us.ibm.com (1a.90.2fa9.ip4.static.sl-reverse.com [169.47.144.26]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvcms9039-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from pps.filterd (ppma04wdc.us.ibm.com [127.0.0.1]) by ppma04wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcC8R028095; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma04wdc.us.ibm.com with ESMTP id 3cqyycns5k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlc6s55247316 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 11583AE064; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EFB7BAE060; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Mehmet Kayaalp , Stefan Berger Subject: [PATCH v6 02/17] ima: Define ns_status for storing namespaced iint data Date: Fri, 10 Dec 2021 14:47:21 -0500 Message-Id: <20211210194736.1538863-3-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: FeEqAj7HKKsrHzmNm6UhTEbv0xeBDSws X-Proofpoint-GUID: QEvLl1SVy7pQ-MnC8zF9He-vBzYIIJRI X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 mlxscore=0 phishscore=0 spamscore=0 malwarescore=0 mlxlogscore=999 priorityscore=1501 suspectscore=0 adultscore=0 clxscore=1015 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: From: Mehmet Kayaalp This patch adds an rbtree to the IMA namespace structure that stores a namespaced version of iint->flags in ns_status struct. Similar to the integrity_iint_cache, both the iint ns_struct are looked up using the inode pointer value. The lookup, allocate, and insertion code is also similar, except ns_struct is not free'd when the inode is free'd. Instead, the lookup verifies the i_ino and i_generation fields are also a match. Signed-off-by: Mehmet Kayaalp Signed-off-by: Stefan Berger Changelog: v2: * fixed tree traversal in __ima_ns_status_find() --- include/linux/ima.h | 4 +- security/integrity/ima/Makefile | 1 + security/integrity/ima/ima.h | 24 +++++ security/integrity/ima/ima_init_ima_ns.c | 7 ++ security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_ns_status.c | 132 +++++++++++++++++++++++ 6 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 security/integrity/ima/ima_ns_status.c diff --git a/include/linux/ima.h b/include/linux/ima.h index f282e40c316c..19e6936250ea 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -212,7 +212,9 @@ static inline int ima_inode_removexattr(struct dentry *dentry, #endif /* CONFIG_IMA_APPRAISE */ struct ima_namespace { - int avoid_zero_size; + struct rb_root ns_status_tree; + rwlock_t ns_status_lock; + struct kmem_cache *ns_status_cache; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index b86a35fbed60..78c84214e109 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -10,6 +10,7 @@ ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ ima_policy.o ima_template.o ima_template_lib.o ima_init_ima_ns.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o +ima-$(CONFIG_IMA_NS) += ima_ns.o ima_ns_status.o ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 2f8adf383054..28896d256e36 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -133,6 +133,14 @@ static inline void ima_load_kexec_buffer(void) {} */ extern bool ima_canonical_fmt; +struct ns_status { + struct rb_node rb_node; + struct inode *inode; + ino_t i_ino; + u32 i_generation; + unsigned long flags; +}; + /* Internal IMA function definitions */ int ima_init(void); int ima_fs_init(void); @@ -422,6 +430,22 @@ int ima_ns_init(void); struct ima_namespace; int ima_init_namespace(struct ima_namespace *ns); +#ifdef CONFIG_IMA_NS +struct ns_status *ima_get_ns_status(struct ima_namespace *ns, + struct inode *inode); + +void free_ns_status_cache(struct ima_namespace *ns); + +#else + +static inline struct ns_status *ima_get_ns_status(struct ima_namespace *ns, + struct inode *inode) +{ + return NULL; +} + +#endif /* CONFIG_IMA_NS */ + /* LSM based policy rules require audit */ #ifdef CONFIG_IMA_LSM_RULES diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index f820686baf9f..08781a44f7bf 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -14,11 +14,18 @@ #include #include #include +#include #include "ima.h" int ima_init_namespace(struct ima_namespace *ns) { + ns->ns_status_tree = RB_ROOT; + rwlock_init(&ns->ns_status_lock); + ns->ns_status_cache = KMEM_CACHE(ns_status, SLAB_PANIC); + if (!ns->ns_status_cache) + return -ENOMEM; + return 0; } diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index c575ddf0c3f3..20472959ec26 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -48,6 +48,7 @@ int create_ima_ns(struct user_namespace *user_ns) static void destroy_ima_ns(struct ima_namespace *ns) { pr_debug("DESTROY ima_ns: 0x%p\n", ns); + free_ns_status_cache(ns); kmem_cache_free(imans_cachep, ns); } diff --git a/security/integrity/ima/ima_ns_status.c b/security/integrity/ima/ima_ns_status.c new file mode 100644 index 000000000000..807dfaecdb5e --- /dev/null +++ b/security/integrity/ima/ima_ns_status.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun + * Stefan Berger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include +#include +#include + +#include "ima.h" + +void free_ns_status_cache(struct ima_namespace *ns) +{ + struct ns_status *status, *next; + + write_lock(&ns->ns_status_lock); + rbtree_postorder_for_each_entry_safe(status, next, + &ns->ns_status_tree, rb_node) + kmem_cache_free(ns->ns_status_cache, status); + ns->ns_status_tree = RB_ROOT; + write_unlock(&ns->ns_status_lock); + kmem_cache_destroy(ns->ns_status_cache); +} + +/* + * __ima_ns_status_find - return the ns_status associated with an inode + */ +static struct ns_status *__ima_ns_status_find(struct ima_namespace *ns, + struct inode *inode) +{ + struct ns_status *status; + struct rb_node *n = ns->ns_status_tree.rb_node; + + while (n) { + status = rb_entry(n, struct ns_status, rb_node); + + if (inode < status->inode) + n = n->rb_left; + else if (inode > status->inode) + n = n->rb_right; + else + break; + } + if (!n) + return NULL; + + return status; +} + +/* + * ima_ns_status_find - return the ns_status associated with an inode + */ +static struct ns_status *ima_ns_status_find(struct ima_namespace *ns, + struct inode *inode) +{ + struct ns_status *status; + + read_lock(&ns->ns_status_lock); + status = __ima_ns_status_find(ns, inode); + read_unlock(&ns->ns_status_lock); + + return status; +} + +static void insert_ns_status(struct ima_namespace *ns, struct inode *inode, + struct ns_status *status) +{ + struct rb_node **p; + struct rb_node *node, *parent = NULL; + struct ns_status *test_status; + + p = &ns->ns_status_tree.rb_node; + while (*p) { + parent = *p; + test_status = rb_entry(parent, struct ns_status, rb_node); + if (inode < test_status->inode) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + node = &status->rb_node; + rb_link_node(node, parent, p); + rb_insert_color(node, &ns->ns_status_tree); +} + +struct ns_status *ima_get_ns_status(struct ima_namespace *ns, + struct inode *inode) +{ + struct ns_status *status; + int skip_insert = 0; + + status = ima_ns_status_find(ns, inode); + if (status) { + /* + * Unlike integrity_iint_cache we are not free'ing the + * ns_status data when the inode is free'd. So, in addition to + * checking the inode pointer, we need to make sure the + * (i_generation, i_ino) pair matches as well. + */ + if (inode->i_ino == status->i_ino && + inode->i_generation == status->i_generation) + return status; + + /* Same inode number is reused, overwrite the ns_status */ + skip_insert = 1; + } else { + status = kmem_cache_alloc(ns->ns_status_cache, GFP_NOFS); + if (!status) + return ERR_PTR(-ENOMEM); + } + + write_lock(&ns->ns_status_lock); + + if (!skip_insert) + insert_ns_status(ns, inode, status); + + status->inode = inode; + status->i_ino = inode->i_ino; + status->i_generation = inode->i_generation; + status->flags = 0UL; + + write_unlock(&ns->ns_status_lock); + + return status; +} From patchwork Fri Dec 10 19:47:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670843 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C9E0C433EF for ; Fri, 10 Dec 2021 19:48:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343941AbhLJTvz (ORCPT ); Fri, 10 Dec 2021 14:51:55 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:41512 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343790AbhLJTvn (ORCPT ); Fri, 10 Dec 2021 14:51:43 -0500 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAI8l0v014636; Fri, 10 Dec 2021 19:47:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=qODHjFfJBjb9nAAdX38NMSiiTn8FyEKYpZt7wkzmGDg=; b=hbO9g61U8AklCTS87TLJ07GTZEMNmDJfTgzrmxtGtC+w3yjFI6vHNbeBcMEjrwl2ig/J /sedUsCC2x/PYQwCrv36RxxDPwr9HpZusR+OP+AFM72bwnjPUeloS5UjEWT9dtx4CbQH 4AQPtUGFgo6It+lhFrx42kAF490sy0pj4gExVX+cXaZ8BmdW7hJ0UJCT4k1xsa+WY90m 23zU9fn/kDrNlUGP8+dVqBoDdoJzPIrymKWPwuuq57hQYdn3uDfnzVVNORbAv+odYPI5 vRItmrvZYHDYhm+sU9WhW6GNg31JOF3qH6E8uQkdtvpndKmnKqVV9XvmlIK+6PwTquLj Qg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjccs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098394.ppops.net (m0098394.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJXhY4031390; Fri, 10 Dec 2021 19:47:40 GMT Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjcc9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcgUK013152; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma01wdc.us.ibm.com with ESMTP id 3cqyycnqje-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlcOj38207864 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 30DBAAE05F; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1C890AE06B; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Mehmet Kayaalp Subject: [PATCH v6 03/17] ima: Namespace audit status flags Date: Fri, 10 Dec 2021 14:47:22 -0500 Message-Id: <20211210194736.1538863-4-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: v5Vx9DDcf10pAYEpjiSCcyKKLzQr5rG7 X-Proofpoint-GUID: NaEPpmroaS0xJ_WHB50YM8c3gdwIPhhy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 phishscore=0 spamscore=0 suspectscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 clxscore=1015 adultscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: From: Mehmet Kayaalp The iint cache stores whether the file is measured, appraised, audited etc. This patch moves the IMA_AUDITED flag into the per-namespace ns_status, enabling IMA audit mechanism to audit the same file each time it is accessed in a new namespace. The ns_status is not looked up if the CONFIG_IMA_NS is disabled or if any of the IMA_NS_STATUS_ACTIONS (currently only IMA_AUDIT) is not enabled. Read and write operations on the iint flags is replaced with function calls. For reading, iint_flags() returns the bitwise AND of iint->flags and ns_status->flags. The ns_status flags are masked with IMA_NS_STATUS_FLAGS (currently only IMA_AUDITED). Similarly set_iint_flags() only writes the masked portion to the ns_status flags, while the iint flags is set as before. The ns_status parameter added to ima_audit_measurement() is used with the above functions to query and set the ns_status flags. Signed-off-by: Mehmet Kayaalp Changelog: v2: * fixed flag calculation in iint_flags() --- init/Kconfig | 3 +++ security/integrity/ima/ima.h | 23 ++++++++++++++++++++++- security/integrity/ima/ima_api.c | 8 +++++--- security/integrity/ima/ima_main.c | 25 ++++++++++++++++++------- security/integrity/ima/ima_ns.c | 20 ++++++++++++++++++++ 5 files changed, 68 insertions(+), 11 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 27890607e8cb..1e1c49f1d129 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1251,6 +1251,9 @@ config IMA_NS Allow the creation of IMA namespaces for each user namespace. Namespaced IMA enables having IMA features work separately in each IMA namespace. + Currently, only the audit status flags are stored in the namespace, + which allows the same file to be audited each time it is accessed + in a new namespace. endif # NAMESPACES diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 28896d256e36..dd06e16c4e1c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -282,7 +282,8 @@ int process_buffer_measurement(struct user_namespace *mnt_userns, int pcr, const char *func_data, bool buf_hash, u8 *digest, size_t digest_len); void ima_audit_measurement(struct integrity_iint_cache *iint, - const unsigned char *filename); + const unsigned char *filename, + struct ns_status *status); int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_entry **entry, struct ima_template_desc *template_desc); @@ -426,6 +427,9 @@ static inline void ima_free_modsig(struct modsig *modsig) } #endif /* CONFIG_IMA_APPRAISE_MODSIG */ +#define IMA_NS_STATUS_ACTIONS IMA_AUDIT +#define IMA_NS_STATUS_FLAGS IMA_AUDITED + int ima_ns_init(void); struct ima_namespace; int ima_init_namespace(struct ima_namespace *ns); @@ -436,6 +440,10 @@ struct ns_status *ima_get_ns_status(struct ima_namespace *ns, void free_ns_status_cache(struct ima_namespace *ns); +unsigned long iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status); +unsigned long set_iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status, unsigned long flags); #else static inline struct ns_status *ima_get_ns_status(struct ima_namespace *ns, @@ -444,6 +452,19 @@ static inline struct ns_status *ima_get_ns_status(struct ima_namespace *ns, return NULL; } +static inline unsigned long iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status) +{ + return iint->flags; +} + +static inline unsigned long set_iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status, + unsigned long flags) +{ + iint->flags = flags; + return flags; +} #endif /* CONFIG_IMA_NS */ /* LSM based policy rules require audit */ diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index a64fb0130b01..8f7bab17b784 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -342,14 +342,16 @@ void ima_store_measurement(struct integrity_iint_cache *iint, } void ima_audit_measurement(struct integrity_iint_cache *iint, - const unsigned char *filename) + const unsigned char *filename, + struct ns_status *status) { struct audit_buffer *ab; char *hash; const char *algo_name = hash_algo_name[iint->ima_hash->algo]; int i; + unsigned long flags = iint_flags(iint, status); - if (iint->flags & IMA_AUDITED) + if (flags & IMA_AUDITED) return; hash = kzalloc((iint->ima_hash->length * 2) + 1, GFP_KERNEL); @@ -372,7 +374,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, audit_log_task_info(ab); audit_log_end(ab); - iint->flags |= IMA_AUDITED; + set_iint_flags(iint, status, flags | IMA_AUDITED); out: kfree(hash); return; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 465865412100..4386010a480e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -202,8 +202,10 @@ static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, enum ima_hooks func) { + struct ima_namespace *ns = get_current_ns(); struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; + struct ns_status *status = NULL; struct ima_template_desc *template_desc = NULL; char *pathbuf = NULL; char filename[NAME_MAX]; @@ -216,6 +218,7 @@ static int process_measurement(struct file *file, const struct cred *cred, bool violation_check; enum hash_algo hash_algo; unsigned int allowed_algos = 0; + unsigned long flags; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; @@ -244,6 +247,12 @@ static int process_measurement(struct file *file, const struct cred *cred, iint = integrity_inode_get(inode); if (!iint) rc = -ENOMEM; + + if (!rc && (action & IMA_NS_STATUS_ACTIONS)) { + status = ima_get_ns_status(ns, inode); + if (IS_ERR(status)) + rc = PTR_ERR(status); + } } if (!rc && violation_check) @@ -259,11 +268,13 @@ static int process_measurement(struct file *file, const struct cred *cred, mutex_lock(&iint->mutex); + flags = iint_flags(iint, status); + if (test_and_clear_bit(IMA_CHANGE_ATTR, &iint->atomic_flags)) /* reset appraisal flags if ima_inode_post_setattr was called */ - iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | - IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | - IMA_ACTION_FLAGS); + flags &= ~(IMA_APPRAISE | IMA_APPRAISED | + IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | + IMA_ACTION_FLAGS); /* * Re-evaulate the file if either the xattr has changed or the @@ -274,7 +285,7 @@ static int process_measurement(struct file *file, const struct cred *cred, ((inode->i_sb->s_iflags & SB_I_IMA_UNVERIFIABLE_SIGNATURE) && !(inode->i_sb->s_iflags & SB_I_UNTRUSTED_MOUNTER) && !(action & IMA_FAIL_UNVERIFIABLE_SIGS))) { - iint->flags &= ~IMA_DONE_MASK; + flags &= ~IMA_DONE_MASK; iint->measured_pcrs = 0; } @@ -282,9 +293,9 @@ static int process_measurement(struct file *file, const struct cred *cred, * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, * IMA_AUDIT, IMA_AUDITED) */ - iint->flags |= action; + flags = set_iint_flags(iint, status, flags | action); action &= IMA_DO_MASK; - action &= ~((iint->flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1); + action &= ~((flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1); /* If target pcr is already measured, unset IMA_MEASURE action */ if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr))) @@ -359,7 +370,7 @@ static int process_measurement(struct file *file, const struct cred *cred, &pathname, filename); } if (action & IMA_AUDIT) - ima_audit_measurement(iint, pathname); + ima_audit_measurement(iint, pathname, status); if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO)) rc = 0; diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 20472959ec26..472535cd7126 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -62,6 +62,26 @@ void free_ima_ns(struct user_namespace *user_ns) destroy_ima_ns(ns); } +unsigned long iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status) +{ + if (!status) + return iint->flags; + + return (iint->flags & ~IMA_NS_STATUS_FLAGS) | + (status->flags & IMA_NS_STATUS_FLAGS); +} + +unsigned long set_iint_flags(struct integrity_iint_cache *iint, + struct ns_status *status, unsigned long flags) +{ + iint->flags = flags; + if (status) + status->flags = flags & IMA_NS_STATUS_FLAGS; + + return flags; +} + static int __init imans_cache_init(void) { imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); From patchwork Fri Dec 10 19:47:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670837 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9C33C433F5 for ; Fri, 10 Dec 2021 19:48:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242413AbhLJTvw (ORCPT ); Fri, 10 Dec 2021 14:51:52 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:42992 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343837AbhLJTvn (ORCPT ); Fri, 10 Dec 2021 14:51:43 -0500 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAIBdnn021647; Fri, 10 Dec 2021 19:47:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=R+pZGmNvVG7emKY0Ef5iuZaEeMQd6uyBrd2oSobvPgA=; b=QJBOE9pXrnXdojSIrkBpEY/kEJXSzPiq91ZbQpNuD/MsL9mL7Db0Bg+v3lof2coGkkcM ROCviG2MLDPvI6ADOlzZas3oCQE6Pn/5HiTxLtF4k0sR894d5N2xRCnWVRwWmHzWwfjI DWzGpyuTR5wuyE2v7Yhgv1jXrdlu6IFRz5Ht+Y2WaJs9xH3WCUhB7RH2+btam03NXZv+ UscuOwpLg3lagzgnC5inr6GDSzM8ZletmAEkMVjbQCW+mJQ8hdpju4zVpGaGNITHgGK6 TbBmg6Hstr8rkCjgcT+3lrik7qxgq+6h4bypYdRQKJpDojGcht0zew1oPLsR+z+pdgIg Mg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvby41tvj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098393.ppops.net (m0098393.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAIcs1o026398; Fri, 10 Dec 2021 19:47:40 GMT Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvby41tva-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcTSl002022; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma04dal.us.ibm.com with ESMTP id 3cqyydbsq3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlc3955247318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5A7ECAE064; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3C68AAE060; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 04/17] ima: Move delayed work queue and variables into ima_namespace Date: Fri, 10 Dec 2021 14:47:23 -0500 Message-Id: <20211210194736.1538863-5-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: mqRIZ2CKwx8B5_-t-gBd9ZHTz5IMD-gz X-Proofpoint-GUID: bm9wVBuOqZL4qg2U1of6dnhQNJAxFFn_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 adultscore=0 spamscore=0 priorityscore=1501 suspectscore=0 mlxlogscore=999 mlxscore=0 phishscore=0 clxscore=1015 malwarescore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move the delayed work queue and associated variables to the ima_namespace and initialize them. Since keys queued up for measurement currently are only relevant in the init_ima_ns, call ima_init_key_queue() only when the init_ima_ns is initialized. Signed-off-by: Stefan Berger --- include/linux/ima.h | 11 ++++++++ security/integrity/ima/ima.h | 12 +++++---- security/integrity/ima/ima_fs.c | 4 ++- security/integrity/ima/ima_init.c | 2 -- security/integrity/ima/ima_init_ima_ns.c | 8 ++++++ security/integrity/ima/ima_policy.c | 4 +-- security/integrity/ima/ima_queue_keys.c | 34 ++++++++++-------------- 7 files changed, 45 insertions(+), 30 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 19e6936250ea..5540ddd39eab 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -215,6 +215,17 @@ struct ima_namespace { struct rb_root ns_status_tree; rwlock_t ns_status_lock; struct kmem_cache *ns_status_cache; + +#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS + /* + * If custom IMA policy is not loaded then keys queued up + * for measurement should be freed. This worker is used + * for handling this scenario. + */ + struct delayed_work ima_keys_delayed_work; + long ima_key_queue_timeout; + bool timer_expired; +#endif }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index dd06e16c4e1c..9edab9050dc7 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -77,6 +77,8 @@ struct ima_field_data { u32 len; }; +struct ima_namespace; + /* IMA template field definition */ struct ima_template_field { const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN]; @@ -247,18 +249,18 @@ struct ima_key_entry { size_t payload_len; char *keyring_name; }; -void ima_init_key_queue(void); +void ima_init_key_queue(struct ima_namespace *ns); bool ima_should_queue_key(void); bool ima_queue_key(struct key *keyring, const void *payload, size_t payload_len); -void ima_process_queued_keys(void); +void ima_process_queued_keys(struct ima_namespace *ns); +void ima_keys_handler(struct work_struct *work); #else -static inline void ima_init_key_queue(void) {} static inline bool ima_should_queue_key(void) { return false; } static inline bool ima_queue_key(struct key *keyring, const void *payload, size_t payload_len) { return false; } -static inline void ima_process_queued_keys(void) {} +static inline void ima_process_queued_keys(struct ima_namespace *ns) {} #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */ /* LIM API function definitions */ @@ -300,7 +302,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, struct ima_template_desc **template_desc, const char *func_data, unsigned int *allowed_algos); void ima_init_policy(void); -void ima_update_policy(void); +void ima_update_policy(struct ima_namespace *ns); void ima_update_policy_flags(void); ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 3d8e9d5db5aa..5cff3d6c3dc7 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "ima.h" @@ -410,6 +411,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) static int ima_release_policy(struct inode *inode, struct file *file) { const char *cause = valid_policy ? "completed" : "failed"; + struct ima_namespace *ns = get_current_ns(); if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); @@ -430,7 +432,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) return 0; } - ima_update_policy(); + ima_update_policy(ns); #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY) securityfs_remove(ima_policy); ima_policy = NULL; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index f6ae4557a0da..24848373a061 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -155,8 +155,6 @@ int __init ima_init(void) if (rc != 0) return rc; - ima_init_key_queue(); - ima_measure_critical_data("kernel_info", "kernel_version", UTS_RELEASE, strlen(UTS_RELEASE), false, NULL, 0); diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index 08781a44f7bf..be31d696bdd3 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -26,6 +26,14 @@ int ima_init_namespace(struct ima_namespace *ns) if (!ns->ns_status_cache) return -ENOMEM; +#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS + INIT_DELAYED_WORK(&ns->ima_keys_delayed_work, ima_keys_handler); + ns->ima_key_queue_timeout = 300000; + ns->timer_expired = false; + if (ns == &init_ima_ns) + ima_init_key_queue(ns); +#endif + return 0; } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 320ca80aacab..e5aef287d14d 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -986,7 +986,7 @@ int ima_check_policy(void) * Policy rules are never deleted so ima_policy_flag gets zeroed only once when * we switch from the default policy to user defined. */ -void ima_update_policy(void) +void ima_update_policy(struct ima_namespace *ns) { struct list_head *policy = &ima_policy_rules; @@ -1007,7 +1007,7 @@ void ima_update_policy(void) ima_update_policy_flags(); /* Custom IMA policy has been loaded */ - ima_process_queued_keys(); + ima_process_queued_keys(ns); } /* Keep the enumeration in sync with the policy_tokens! */ diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index 93056c03bf5a..fcaa1645dba3 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "ima.h" @@ -25,34 +26,27 @@ static bool ima_process_keys; static DEFINE_MUTEX(ima_keys_lock); static LIST_HEAD(ima_keys); -/* - * If custom IMA policy is not loaded then keys queued up - * for measurement should be freed. This worker is used - * for handling this scenario. - */ -static long ima_key_queue_timeout = 300000; /* 5 Minutes */ -static void ima_keys_handler(struct work_struct *work); -static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler); -static bool timer_expired; - /* * This worker function frees keys that may still be * queued up in case custom IMA policy was not loaded. */ -static void ima_keys_handler(struct work_struct *work) +void ima_keys_handler(struct work_struct *work) { - timer_expired = true; - ima_process_queued_keys(); + struct ima_namespace *ns; + + ns = container_of(work, struct ima_namespace, ima_keys_delayed_work.work); + ns->timer_expired = true; + ima_process_queued_keys(ns); } /* * This function sets up a worker to free queued keys in case * custom IMA policy was never loaded. */ -void ima_init_key_queue(void) +void ima_init_key_queue(struct ima_namespace *ns) { - schedule_delayed_work(&ima_keys_delayed_work, - msecs_to_jiffies(ima_key_queue_timeout)); + schedule_delayed_work(&ns->ima_keys_delayed_work, + msecs_to_jiffies(ns->ima_key_queue_timeout)); } static void ima_free_key_entry(struct ima_key_entry *entry) @@ -130,7 +124,7 @@ bool ima_queue_key(struct key *keyring, const void *payload, * This function sets ima_process_keys to true and processes queued keys. * From here on keys will be processed right away (not queued). */ -void ima_process_queued_keys(void) +void ima_process_queued_keys(struct ima_namespace *ns) { struct ima_key_entry *entry, *tmp; bool process = false; @@ -154,11 +148,11 @@ void ima_process_queued_keys(void) if (!process) return; - if (!timer_expired) - cancel_delayed_work_sync(&ima_keys_delayed_work); + if (!ns->timer_expired) + cancel_delayed_work_sync(&ns->ima_keys_delayed_work); list_for_each_entry_safe(entry, tmp, &ima_keys, list) { - if (!timer_expired) + if (!ns->timer_expired) process_buffer_measurement(&init_user_ns, NULL, entry->payload, entry->payload_len, From patchwork Fri Dec 10 19:47:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670835 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D631C433FE for ; Fri, 10 Dec 2021 19:48:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343910AbhLJTvu (ORCPT ); Fri, 10 Dec 2021 14:51:50 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:58866 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343846AbhLJTvo (ORCPT ); Fri, 10 Dec 2021 14:51:44 -0500 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAI8KQW012860; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=N/0Wp5GJail43pfcaRX3jP2LFfrcuRlW+4P5TwZnAsY=; b=UJgN47jLV1S84eCY1XoGS55w6FASx1pPjOlHWyea1vpzTlkccqgHgUc61/s1atd3YsWG IoOADA5cY21Okphom9mGdLmKCBv6ZYgc5X4JlV3FJCw+8O3VkQQztQu/0huZ3rCpBz6Y HigAPV1hIM84xx23EEE9MSK0dA1D5zlkiD4pK+I6hRk/3VAmxXGcrJ2JLWQtU7Eiyf8t gP1GZEdx66la5dtMmj0qbsw7Nt5lbg1o8fls66gFpQKVtLzEvbUQY+99tB/eCFgvyea6 FtW0WOc62mFGV+ugee0yJ8H9VrY7+pXdC/7oTzd6RHu3Kzeg3llQpGsQ2r2GcaFmz3hX Sg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjcd0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098394.ppops.net (m0098394.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAIkwIs005293; Fri, 10 Dec 2021 19:47:40 GMT Received: from ppma02wdc.us.ibm.com (aa.5b.37a9.ip4.static.sl-reverse.com [169.55.91.170]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjccb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from pps.filterd (ppma02wdc.us.ibm.com [127.0.0.1]) by ppma02wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcKxs016563; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma02wdc.us.ibm.com with ESMTP id 3cqyycnqgg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlcdu25559488 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 79244AE060; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5BE7FAE05F; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 05/17] ima: Move IMA's keys queue related variables into ima_namespace Date: Fri, 10 Dec 2021 14:47:24 -0500 Message-Id: <20211210194736.1538863-6-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: ohW5Pc-TLuXnYuoRt7PJFBgOtx5xfc8w X-Proofpoint-GUID: X6YGMrcct8A6UDMLZ-tuzw5Bhnd767zA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 phishscore=0 spamscore=0 suspectscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 clxscore=1015 adultscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move variables from keys queue into ima_namespace. Some variables have to be initialized before ima_init() runs, so statically initialize them for the init_ima_ns. Since only init_ima_ns uses the queued keys there's no need to free the list of queued keys when tearing down IMA namespaces. Signed-off-by: Stefan Berger --- include/linux/ima.h | 11 ++++++ security/integrity/ima/ima.h | 9 ++--- security/integrity/ima/ima_asymmetric_keys.c | 5 +-- security/integrity/ima/ima_init_ima_ns.c | 5 +++ security/integrity/ima/ima_ns.c | 6 ++++ security/integrity/ima/ima_queue_keys.c | 37 +++++++------------- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 5540ddd39eab..41b6d7d4c312 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -217,6 +217,17 @@ struct ima_namespace { struct kmem_cache *ns_status_cache; #ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS + /* + * Flag to indicate whether a key can be processed + * right away or should be queued for processing later. + */ + bool ima_process_keys; + + /* + * To synchronize access to the list of keys that need to be measured + */ + struct mutex ima_keys_lock; + struct list_head ima_keys; /* * If custom IMA policy is not loaded then keys queued up * for measurement should be freed. This worker is used diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 9edab9050dc7..97eb03376855 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -250,14 +250,15 @@ struct ima_key_entry { char *keyring_name; }; void ima_init_key_queue(struct ima_namespace *ns); -bool ima_should_queue_key(void); -bool ima_queue_key(struct key *keyring, const void *payload, +bool ima_should_queue_key(struct ima_namespace *ns); +bool ima_queue_key(struct ima_namespace *ns, struct key *keyring, const void *payload, size_t payload_len); void ima_process_queued_keys(struct ima_namespace *ns); void ima_keys_handler(struct work_struct *work); #else -static inline bool ima_should_queue_key(void) { return false; } -static inline bool ima_queue_key(struct key *keyring, +static inline bool ima_should_queue_key(struct ima_namespace *ns) { return false; } +static inline bool ima_queue_key(struct ima_namespace *ns, + struct key *keyring, const void *payload, size_t payload_len) { return false; } static inline void ima_process_queued_keys(struct ima_namespace *ns) {} diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index f6aa0b47a772..b20e82eda8f4 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -30,6 +30,7 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, const void *payload, size_t payload_len, unsigned long flags, bool create) { + struct ima_namespace *ns = get_current_ns(); bool queued = false; /* Only asymmetric keys are handled by this hook. */ @@ -39,8 +40,8 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, if (!payload || (payload_len == 0)) return; - if (ima_should_queue_key()) - queued = ima_queue_key(keyring, payload, payload_len); + if (ima_should_queue_key(ns)) + queued = ima_queue_key(ns, keyring, payload, payload_len); if (queued) return; diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index be31d696bdd3..d2a36b5251cd 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -43,5 +43,10 @@ int __init ima_ns_init(void) } struct ima_namespace init_ima_ns = { +#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS + .ima_process_keys = false, + .ima_keys_lock = __MUTEX_INITIALIZER(init_ima_ns.ima_keys_lock), + .ima_keys = LIST_HEAD_INIT(init_ima_ns.ima_keys), +#endif }; EXPORT_SYMBOL(init_ima_ns); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 472535cd7126..155126038809 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -35,6 +35,12 @@ int create_ima_ns(struct user_namespace *user_ns) if (err) goto fail_free; +#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS + ns->ima_process_keys = false; + mutex_init(&ns->ima_keys_lock); + INIT_LIST_HEAD(&ns->ima_keys); +#endif + user_ns->ima_ns = ns; return 0; diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index fcaa1645dba3..9e5e9a178253 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -14,17 +14,6 @@ #include #include "ima.h" -/* - * Flag to indicate whether a key can be processed - * right away or should be queued for processing later. - */ -static bool ima_process_keys; - -/* - * To synchronize access to the list of keys that need to be measured - */ -static DEFINE_MUTEX(ima_keys_lock); -static LIST_HEAD(ima_keys); /* * This worker function frees keys that may still be @@ -95,7 +84,7 @@ static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring, return entry; } -bool ima_queue_key(struct key *keyring, const void *payload, +bool ima_queue_key(struct ima_namespace *ns, struct key *keyring, const void *payload, size_t payload_len) { bool queued = false; @@ -105,12 +94,12 @@ bool ima_queue_key(struct key *keyring, const void *payload, if (!entry) return false; - mutex_lock(&ima_keys_lock); - if (!ima_process_keys) { - list_add_tail(&entry->list, &ima_keys); + mutex_lock(&ns->ima_keys_lock); + if (!ns->ima_process_keys) { + list_add_tail(&entry->list, &ns->ima_keys); queued = true; } - mutex_unlock(&ima_keys_lock); + mutex_unlock(&ns->ima_keys_lock); if (!queued) ima_free_key_entry(entry); @@ -129,7 +118,7 @@ void ima_process_queued_keys(struct ima_namespace *ns) struct ima_key_entry *entry, *tmp; bool process = false; - if (ima_process_keys) + if (ns->ima_process_keys) return; /* @@ -138,12 +127,12 @@ void ima_process_queued_keys(struct ima_namespace *ns) * First one setting the ima_process_keys flag to true will * process the queued keys. */ - mutex_lock(&ima_keys_lock); - if (!ima_process_keys) { - ima_process_keys = true; + mutex_lock(&ns->ima_keys_lock); + if (!ns->ima_process_keys) { + ns->ima_process_keys = true; process = true; } - mutex_unlock(&ima_keys_lock); + mutex_unlock(&ns->ima_keys_lock); if (!process) return; @@ -151,7 +140,7 @@ void ima_process_queued_keys(struct ima_namespace *ns) if (!ns->timer_expired) cancel_delayed_work_sync(&ns->ima_keys_delayed_work); - list_for_each_entry_safe(entry, tmp, &ima_keys, list) { + list_for_each_entry_safe(entry, tmp, &ns->ima_keys, list) { if (!ns->timer_expired) process_buffer_measurement(&init_user_ns, NULL, entry->payload, @@ -165,7 +154,7 @@ void ima_process_queued_keys(struct ima_namespace *ns) } } -inline bool ima_should_queue_key(void) +inline bool ima_should_queue_key(struct ima_namespace *ns) { - return !ima_process_keys; + return !ns->ima_process_keys; } From patchwork Fri Dec 10 19:47:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670885 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34D32C433F5 for ; Fri, 10 Dec 2021 19:49:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343798AbhLJTvk (ORCPT ); Fri, 10 Dec 2021 14:51:40 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:44074 "EHLO mx0b-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343728AbhLJTvc (ORCPT ); Fri, 10 Dec 2021 14:51:32 -0500 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAHoFqI015775; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=K9CKjm/05lDUWN+xhUrovSaJlvVCdDLF9tV3fRb7JPg=; b=iWeiKxmsHTjVceUF+5YosBH1udwmrWTtNPTiRYw3CC0ARiyktOa+C5IzQojt2JDnrk1q 3wcK7Zfd+/rpMz1E9XXHOLpf1d9V6QAxgJQi2HBsln2vwnXAFD05LJwpeXgLk9sK5KGV 7yznkz+GdXtikh6evnSKR9XCVrF8jLG4T6HBsWDbN/DWBOD0NL7r7OZWgeXh5IpezICr EWP4OtblwxTlnxaYluBoATsq1yiTu6Bj/wUG1RA1XvmGd5eY/bSKvYBgoRIpZSPbsTxo RdbqZNdT88uFNt/Bhf7tJqVXIZM7Y4GrPET/YAikgrKDpL5+e56uiuJJ0mkvA5n2jsXR ww== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubh0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098421.ppops.net (m0098421.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJlTYv010342; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubgh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJc5xs011579; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma01dal.us.ibm.com with ESMTP id 3cqyyekvyk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlcaS42991872 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AE87EAE067; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7CD7FAE064; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 06/17] ima: Move policy related variables into ima_namespace Date: Fri, 10 Dec 2021 14:47:25 -0500 Message-Id: <20211210194736.1538863-7-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: zQ_uicBC1YfbojJTRbtVOCNws-OGEAdt X-Proofpoint-GUID: u8EVmTS1Wdb_rdGrKtby6rvPCrzqDzhW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 phishscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 spamscore=0 mlxlogscore=999 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move variables related to the IMA policy into the ima_namespace. This way the IMA policy of an IMA namespace can be set and displayed using a front-end like SecurityFS. Implement ima_free_policy_rules() that frees the policy rules on ima_namespace deletion. Signed-off-by: Stefan Berger --- include/linux/ima.h | 10 ++ security/integrity/ima/ima.h | 35 ++--- security/integrity/ima/ima_api.c | 8 +- security/integrity/ima/ima_appraise.c | 26 ++-- security/integrity/ima/ima_asymmetric_keys.c | 3 +- security/integrity/ima/ima_fs.c | 10 +- security/integrity/ima/ima_init.c | 8 +- security/integrity/ima/ima_init_ima_ns.c | 6 + security/integrity/ima/ima_main.c | 83 +++++++----- security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_policy.c | 132 +++++++++++-------- security/integrity/ima/ima_queue_keys.c | 2 +- 12 files changed, 196 insertions(+), 128 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 41b6d7d4c312..7a81e2d9fef0 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -237,9 +237,19 @@ struct ima_namespace { long ima_key_queue_timeout; bool timer_expired; #endif + + struct list_head ima_default_rules; + /* ns's policy rules */ + struct list_head ima_policy_rules; + struct list_head ima_temp_rules; + /* Pointer to ns's current policy */ + struct list_head __rcu *ima_rules; + /* current content of the policy */ + int ima_policy_flag; }; extern struct ima_namespace init_ima_ns; +extern struct list_head ima_default_rules; #ifdef CONFIG_IMA_NS diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 97eb03376855..e295141f2478 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -43,9 +43,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) -/* current content of the policy */ -extern int ima_policy_flag; - /* bitset of digests algorithms allowed in the setxattr hook */ extern atomic_t ima_setxattr_allowed_hash_algorithms; @@ -265,7 +262,8 @@ static inline void ima_process_queued_keys(struct ima_namespace *ns) {} #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */ /* LIM API function definitions */ -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, +int ima_get_action(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, @@ -279,7 +277,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, struct ima_template_desc *template_desc); -int process_buffer_measurement(struct user_namespace *mnt_userns, +int process_buffer_measurement(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const void *buf, int size, const char *eventname, enum ima_hooks func, int pcr, const char *func_data, @@ -297,17 +296,19 @@ void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); /* IMA policy related functions */ -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, +int ima_match_policy(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, const char *func_data, unsigned int *allowed_algos); -void ima_init_policy(void); +void ima_init_policy(struct ima_namespace *ns); void ima_update_policy(struct ima_namespace *ns); -void ima_update_policy_flags(void); -ssize_t ima_parse_add_rule(char *); -void ima_delete_rules(void); -int ima_check_policy(void); +void ima_update_policy_flags(struct ima_namespace *ns); +ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule); +void ima_delete_rules(struct ima_namespace *ns); +int ima_check_policy(struct ima_namespace *ns); +void ima_free_policy_rules(struct ima_namespace *ns); void *ima_policy_start(struct seq_file *m, loff_t *pos); void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos); void ima_policy_stop(struct seq_file *m, void *v); @@ -323,14 +324,16 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_KEXEC 0x40 #ifdef CONFIG_IMA_APPRAISE -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_namespace *ns, + struct integrity_iint_cache *iint, const struct modsig *modsig, int pcr); int ima_appraise_measurement(enum ima_hooks func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig); -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode, +int ima_must_appraise(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, @@ -341,7 +344,8 @@ int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value); #else -static inline int ima_check_blacklist(struct integrity_iint_cache *iint, +static inline int ima_check_blacklist(struct ima_namespace *ns, + struct integrity_iint_cache *iint, const struct modsig *modsig, int pcr) { return 0; @@ -358,7 +362,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func, return INTEGRITY_UNKNOWN; } -static inline int ima_must_appraise(struct user_namespace *mnt_userns, +static inline int ima_must_appraise(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, int mask, enum ima_hooks func) { diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 8f7bab17b784..808aec56dbb6 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "ima.h" @@ -185,7 +186,8 @@ void ima_add_violation(struct file *file, const unsigned char *filename, * Returns IMA_MEASURE, IMA_APPRAISE mask. * */ -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, +int ima_get_action(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, struct ima_template_desc **template_desc, @@ -193,9 +195,9 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; - flags &= ima_policy_flag; + flags &= ns->ima_policy_flag; - return ima_match_policy(mnt_userns, inode, cred, secid, func, mask, + return ima_match_policy(ns, mnt_userns, inode, cred, secid, func, mask, flags, pcr, template_desc, func_data, allowed_algos); } diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index dbba51583e7c..b0c1992d8c4b 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -68,7 +68,8 @@ bool is_ima_appraise_enabled(void) * * Return 1 to appraise or hash */ -int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode, +int ima_must_appraise(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, int mask, enum ima_hooks func) { u32 secid; @@ -77,7 +78,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode, return 0; security_task_getsecid_subj(current, &secid); - return ima_match_policy(mnt_userns, inode, current_cred(), secid, + return ima_match_policy(ns, mnt_userns, inode, current_cred(), secid, func, mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL, NULL); } @@ -341,7 +342,8 @@ static int modsig_verify(enum ima_hooks func, const struct modsig *modsig, * * Returns -EPERM if the hash is blacklisted. */ -int ima_check_blacklist(struct integrity_iint_cache *iint, +int ima_check_blacklist(struct ima_namespace *ns, + struct integrity_iint_cache *iint, const struct modsig *modsig, int pcr) { enum hash_algo hash_algo; @@ -357,7 +359,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, rc = is_binary_blacklisted(digest, digestsize); if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) - process_buffer_measurement(&init_user_ns, NULL, digest, digestsize, + process_buffer_measurement(ns, &init_user_ns, NULL, digest, digestsize, "blacklisted-hash", NONE, pcr, NULL, false, NULL, 0); } @@ -527,14 +529,15 @@ void ima_inode_post_setattr(struct user_namespace *mnt_userns, struct dentry *dentry) { struct inode *inode = d_backing_inode(dentry); + struct ima_namespace *ns = get_current_ns(); struct integrity_iint_cache *iint; int action; - if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) + if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) || !(inode->i_opflags & IOP_XATTR)) return; - action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR); + action = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS, POST_SETATTR); iint = integrity_iint_find(inode); if (iint) { set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); @@ -559,11 +562,12 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, return 0; } -static void ima_reset_appraise_flags(struct inode *inode, int digsig) +static void ima_reset_appraise_flags(struct ima_namespace *ns, + struct inode *inode, int digsig) { struct integrity_iint_cache *iint; - if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) + if (!(ns->ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return; iint = integrity_iint_find(inode); @@ -641,6 +645,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, const void *xattr_value, size_t xattr_value_len) { const struct evm_ima_xattr_data *xvalue = xattr_value; + struct ima_namespace *ns = get_current_ns(); int digsig = 0; int result; @@ -658,18 +663,19 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, if (result) return result; - ima_reset_appraise_flags(d_backing_inode(dentry), digsig); + ima_reset_appraise_flags(ns, d_backing_inode(dentry), digsig); } return result; } int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) { + struct ima_namespace *ns = get_current_ns(); int result; result = ima_protect_xattr(dentry, xattr_name, NULL, 0); if (result == 1 || evm_revalidate_status(xattr_name)) { - ima_reset_appraise_flags(d_backing_inode(dentry), 0); + ima_reset_appraise_flags(ns, d_backing_inode(dentry), 0); if (result == 1) result = 0; } diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index b20e82eda8f4..959e9f2f6c26 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -61,7 +61,8 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, * if the IMA policy is configured to measure a key linked * to the given keyring. */ - process_buffer_measurement(&init_user_ns, NULL, payload, payload_len, + process_buffer_measurement(ns, &init_user_ns, NULL, + payload, payload_len, keyring->description, KEY_CHECK, 0, keyring->description, false, NULL, 0); } diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 5cff3d6c3dc7..25f85c58ebef 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -274,6 +274,7 @@ static const struct file_operations ima_ascii_measurements_ops = { static ssize_t ima_read_policy(char *path) { + struct ima_namespace *ns = get_current_ns(); void *data = NULL; char *datap; size_t size; @@ -297,7 +298,7 @@ static ssize_t ima_read_policy(char *path) datap = data; while (size > 0 && (p = strsep(&datap, "\n"))) { pr_debug("rule: %s\n", p); - rc = ima_parse_add_rule(p); + rc = ima_parse_add_rule(ns, p); if (rc < 0) break; size -= rc; @@ -315,6 +316,7 @@ static ssize_t ima_read_policy(char *path) static ssize_t ima_write_policy(struct file *file, const char __user *buf, size_t datalen, loff_t *ppos) { + struct ima_namespace *ns = get_current_ns(); char *data; ssize_t result; @@ -345,7 +347,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, 1, 0); result = -EACCES; } else { - result = ima_parse_add_rule(data); + result = ima_parse_add_rule(ns, data); } mutex_unlock(&ima_write_mutex); out_free: @@ -416,7 +418,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); - if (valid_policy && ima_check_policy() < 0) { + if (valid_policy && ima_check_policy(ns) < 0) { cause = "failed"; valid_policy = 0; } @@ -426,7 +428,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) "policy_update", cause, !valid_policy, 0); if (!valid_policy) { - ima_delete_rules(); + ima_delete_rules(ns); valid_policy = 1; clear_bit(IMA_FS_BUSY, &ima_fs_flags); return 0; diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 24848373a061..d78f8faf6dcd 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -104,15 +104,15 @@ static int __init ima_add_boot_aggregate(void) #ifdef CONFIG_IMA_LOAD_X509 void __init ima_load_x509(void) { - int unset_flags = ima_policy_flag & IMA_APPRAISE; + int unset_flags = init_ima_ns.ima_policy_flag & IMA_APPRAISE; - ima_policy_flag &= ~unset_flags; + init_ima_ns.ima_policy_flag &= ~unset_flags; integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH); /* load also EVM key to avoid appraisal */ evm_load_x509(); - ima_policy_flag |= unset_flags; + init_ima_ns.ima_policy_flag |= unset_flags; } #endif @@ -149,7 +149,7 @@ int __init ima_init(void) if (rc != 0) return rc; - ima_init_policy(); + ima_init_policy(&init_ima_ns); rc = ima_fs_init(); if (rc != 0) diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index d2a36b5251cd..db7de6811fcc 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -34,6 +34,12 @@ int ima_init_namespace(struct ima_namespace *ns) ima_init_key_queue(ns); #endif + INIT_LIST_HEAD(&ns->ima_default_rules); + INIT_LIST_HEAD(&ns->ima_policy_rules); + INIT_LIST_HEAD(&ns->ima_temp_rules); + ns->ima_rules = (struct list_head __rcu *)(&ns->ima_default_rules); + ns->ima_policy_flag = 0; + return 0; } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4386010a480e..897304046ba4 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -185,10 +185,11 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, */ void ima_file_free(struct file *file) { + struct ima_namespace *ns = get_current_ns(); struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode)) return; iint = integrity_iint_find(inode); @@ -198,11 +199,11 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } -static int process_measurement(struct file *file, const struct cred *cred, +static int process_measurement(struct ima_namespace *ns, + struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, enum ima_hooks func) { - struct ima_namespace *ns = get_current_ns(); struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; struct ns_status *status = NULL; @@ -220,18 +221,18 @@ static int process_measurement(struct file *file, const struct cred *cred, unsigned int allowed_algos = 0; unsigned long flags; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action * bitmask based on the appraise/audit/measurement policy. * Included is the appraise submask. */ - action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid, + action = ima_get_action(ns, file_mnt_user_ns(file), inode, cred, secid, mask, func, &pcr, &template_desc, NULL, &allowed_algos); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && - (ima_policy_flag & IMA_MEASURE)); + (ns->ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0; @@ -357,7 +358,7 @@ static int process_measurement(struct file *file, const struct cred *cred, xattr_value, xattr_len, modsig, pcr, template_desc); if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { - rc = ima_check_blacklist(iint, modsig, pcr); + rc = ima_check_blacklist(ns, iint, modsig, pcr); if (rc != -EPERM) { inode_lock(inode); rc = ima_appraise_measurement(func, iint, file, @@ -416,12 +417,13 @@ static int process_measurement(struct file *file, const struct cred *cred, */ int ima_file_mmap(struct file *file, unsigned long prot) { + struct ima_namespace *ns = get_current_ns(); u32 secid; if (file && (prot & PROT_EXEC)) { security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_EXEC, MMAP_CHECK); + return process_measurement(ns, file, current_cred(), secid, + NULL, 0, MAY_EXEC, MMAP_CHECK); } return 0; @@ -441,6 +443,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { + struct ima_namespace *ns = get_current_ns(); struct ima_template_desc *template = NULL; struct file *file = vma->vm_file; char filename[NAME_MAX]; @@ -453,13 +456,13 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) int pcr; /* Is mprotect making an mmap'ed file executable? */ - if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || + if (!(ns->ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) return 0; security_task_getsecid_subj(current, &secid); inode = file_inode(vma->vm_file); - action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode, + action = ima_get_action(ns, file_mnt_user_ns(vma->vm_file), inode, current_cred(), secid, MAY_EXEC, MMAP_CHECK, &pcr, &template, NULL, NULL); @@ -495,17 +498,18 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) */ int ima_bprm_check(struct linux_binprm *bprm) { + struct ima_namespace *ns = get_current_ns(); int ret; u32 secid; security_task_getsecid_subj(current, &secid); - ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, - MAY_EXEC, BPRM_CHECK); + ret = process_measurement(ns, bprm->file, current_cred(), secid, NULL, + 0, MAY_EXEC, BPRM_CHECK); if (ret) return ret; security_cred_getsecid(bprm->cred, &secid); - return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, + return process_measurement(ns, bprm->file, bprm->cred, secid, NULL, 0, MAY_EXEC, CREDS_CHECK); } @@ -521,21 +525,23 @@ int ima_bprm_check(struct linux_binprm *bprm) */ int ima_file_check(struct file *file, int mask) { + struct ima_namespace *ns = get_current_ns(); u32 secid; security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, 0, + return process_measurement(ns, file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND), FILE_CHECK); } EXPORT_SYMBOL_GPL(ima_file_check); -static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) +static int __ima_inode_hash(struct ima_namespace *ns, + struct inode *inode, char *buf, size_t buf_size) { struct integrity_iint_cache *iint; int hash_algo; - if (!ima_policy_flag) + if (!ns->ima_policy_flag) return -EOPNOTSUPP; iint = integrity_iint_find(inode); @@ -585,10 +591,12 @@ static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) */ int ima_file_hash(struct file *file, char *buf, size_t buf_size) { + struct ima_namespace *ns = get_current_ns(); + if (!file) return -EINVAL; - return __ima_inode_hash(file_inode(file), buf, buf_size); + return __ima_inode_hash(ns, file_inode(file), buf, buf_size); } EXPORT_SYMBOL_GPL(ima_file_hash); @@ -612,10 +620,12 @@ EXPORT_SYMBOL_GPL(ima_file_hash); */ int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) { + struct ima_namespace *ns = get_current_ns(); + if (!inode) return -EINVAL; - return __ima_inode_hash(inode, buf, buf_size); + return __ima_inode_hash(ns, inode, buf, buf_size); } EXPORT_SYMBOL_GPL(ima_inode_hash); @@ -631,13 +641,14 @@ EXPORT_SYMBOL_GPL(ima_inode_hash); void ima_post_create_tmpfile(struct user_namespace *mnt_userns, struct inode *inode) { + struct ima_namespace *ns = get_current_ns(); struct integrity_iint_cache *iint; int must_appraise; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode)) return; - must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, + must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS, FILE_CHECK); if (!must_appraise) return; @@ -663,14 +674,15 @@ void ima_post_create_tmpfile(struct user_namespace *mnt_userns, void ima_post_path_mknod(struct user_namespace *mnt_userns, struct dentry *dentry) { + struct ima_namespace *ns = get_current_ns(); struct integrity_iint_cache *iint; struct inode *inode = dentry->d_inode; int must_appraise; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ns->ima_policy_flag || !S_ISREG(inode->i_mode)) return; - must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, + must_appraise = ima_must_appraise(ns, mnt_userns, inode, MAY_ACCESS, FILE_CHECK); if (!must_appraise) return; @@ -699,6 +711,7 @@ void ima_post_path_mknod(struct user_namespace *mnt_userns, int ima_read_file(struct file *file, enum kernel_read_file_id read_id, bool contents) { + struct ima_namespace *ns = get_current_ns(); enum ima_hooks func; u32 secid; @@ -721,7 +734,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, /* Read entire file for all partial reads. */ func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, + return process_measurement(ns, file, current_cred(), secid, NULL, 0, MAY_READ, func); } @@ -749,6 +762,7 @@ const int read_idmap[READING_MAX_ID] = { int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id read_id) { + struct ima_namespace *ns = get_current_ns(); enum ima_hooks func; u32 secid; @@ -764,7 +778,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, buf, size, + return process_measurement(ns, file, current_cred(), secid, buf, size, MAY_READ, func); } @@ -870,7 +884,8 @@ int ima_post_load_data(char *buf, loff_t size, * has been written to the passed location but not added to a measurement entry, * a negative value otherwise. */ -int process_buffer_measurement(struct user_namespace *mnt_userns, +int process_buffer_measurement(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const void *buf, int size, const char *eventname, enum ima_hooks func, int pcr, const char *func_data, @@ -898,7 +913,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns, if (digest && digest_len < digest_hash_len) return -EINVAL; - if (!ima_policy_flag && !digest) + if (!ns->ima_policy_flag && !digest) return -ENOENT; template = ima_template_desc_buf(); @@ -917,7 +932,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns, */ if (func) { security_task_getsecid_subj(current, &secid); - action = ima_get_action(mnt_userns, inode, current_cred(), + action = ima_get_action(ns, mnt_userns, inode, current_cred(), secid, 0, func, &pcr, &template, func_data, NULL); if (!(action & IMA_MEASURE) && !digest) @@ -954,7 +969,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns, if (digest) memcpy(digest, iint.ima_hash->digest, digest_hash_len); - if (!ima_policy_flag || (func && !(action & IMA_MEASURE))) + if (!ns->ima_policy_flag || (func && !(action & IMA_MEASURE))) return 1; ret = ima_alloc_init_template(&event_data, &entry, template); @@ -988,6 +1003,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns, */ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) { + struct ima_namespace *ns = get_current_ns(); struct fd f; if (!buf || !size) @@ -997,7 +1013,8 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) if (!f.file) return; - process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file), + process_buffer_measurement(ns, + file_mnt_user_ns(f.file), file_inode(f.file), buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, NULL, false, NULL, 0); fdput(f); @@ -1027,10 +1044,12 @@ int ima_measure_critical_data(const char *event_label, const void *buf, size_t buf_len, bool hash, u8 *digest, size_t digest_len) { + struct ima_namespace *ns = get_current_ns(); + if (!event_name || !event_label || !buf || !buf_len) return -ENOPARAM; - return process_buffer_measurement(&init_user_ns, NULL, buf, buf_len, + return process_buffer_measurement(ns, &init_user_ns, NULL, buf, buf_len, event_name, CRITICAL_DATA, 0, event_label, hash, digest, digest_len); @@ -1063,7 +1082,7 @@ static int __init init_ima(void) pr_warn("Couldn't register LSM notifier, error %d\n", error); if (!error) - ima_update_policy_flags(); + ima_update_policy_flags(&init_ima_ns); return error; } diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 155126038809..9d97f45fa8e4 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -54,6 +54,7 @@ int create_ima_ns(struct user_namespace *user_ns) static void destroy_ima_ns(struct ima_namespace *ns) { pr_debug("DESTROY ima_ns: 0x%p\n", ns); + ima_free_policy_rules(ns); free_ns_status_cache(ns); kmem_cache_free(imans_cachep, ns); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index e5aef287d14d..4d6d3a39f65e 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -52,7 +52,6 @@ #define INVALID_PCR(a) (((a) < 0) || \ (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8)) -int ima_policy_flag; static int temp_ima_appraise; static int build_ima_appraise __ro_after_init; @@ -233,11 +232,6 @@ static struct ima_rule_entry critical_data_rules[] __ro_after_init = { /* An array of architecture specific rules */ static struct ima_rule_entry *arch_policy_entry __ro_after_init; -static LIST_HEAD(ima_default_rules); -static LIST_HEAD(ima_policy_rules); -static LIST_HEAD(ima_temp_rules); -static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules); - static int ima_policy __initdata; static int __init default_measure_policy_setup(char *str) @@ -454,12 +448,12 @@ static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry) * to the old, stale LSM policy. Update the IMA LSM based rules to reflect * the reloaded LSM policy. */ -static void ima_lsm_update_rules(void) +static void ima_lsm_update_rules(struct ima_namespace *ns) { struct ima_rule_entry *entry, *e; int result; - list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { + list_for_each_entry_safe(entry, e, &ns->ima_policy_rules, list) { if (!ima_rule_contains_lsm_cond(entry)) continue; @@ -474,10 +468,12 @@ static void ima_lsm_update_rules(void) int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, void *lsm_data) { + struct ima_namespace *ns = get_current_ns(); + if (event != LSM_POLICY_CHANGE) return NOTIFY_DONE; - ima_lsm_update_rules(); + ima_lsm_update_rules(ns); return NOTIFY_OK; } @@ -688,7 +684,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * list when walking it. Reads are many orders of magnitude more numerous * than writes so ima_match_policy() is classical RCU candidate. */ -int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, +int ima_match_policy(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, struct ima_template_desc **template_desc, @@ -702,7 +699,7 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, *template_desc = ima_template_desc_current(); rcu_read_lock(); - ima_rules_tmp = rcu_dereference(ima_rules); + ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) { if (!(entry->action & actmask)) @@ -760,14 +757,14 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode, * * Context: called after a policy update and at system initialization. */ -void ima_update_policy_flags(void) +void ima_update_policy_flags(struct ima_namespace *ns) { struct ima_rule_entry *entry; int new_policy_flag = 0; struct list_head *ima_rules_tmp; rcu_read_lock(); - ima_rules_tmp = rcu_dereference(ima_rules); + ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) { /* * SETXATTR_CHECK rules do not implement a full policy check @@ -797,7 +794,7 @@ void ima_update_policy_flags(void) if (!ima_appraise) new_policy_flag &= ~IMA_APPRAISE; - ima_policy_flag = new_policy_flag; + ns->ima_policy_flag = new_policy_flag; } static int ima_appraise_flag(enum ima_hooks func) @@ -813,7 +810,8 @@ static int ima_appraise_flag(enum ima_hooks func) return 0; } -static void add_rules(struct ima_rule_entry *entries, int count, +static void add_rules(struct ima_namespace *ns, + struct ima_rule_entry *entries, int count, enum policy_rule_list policy_rule) { int i = 0; @@ -822,7 +820,7 @@ static void add_rules(struct ima_rule_entry *entries, int count, struct ima_rule_entry *entry; if (policy_rule & IMA_DEFAULT_POLICY) - list_add_tail(&entries[i].list, &ima_default_rules); + list_add_tail(&entries[i].list, &ns->ima_default_rules); if (policy_rule & IMA_CUSTOM_POLICY) { entry = kmemdup(&entries[i], sizeof(*entry), @@ -830,7 +828,7 @@ static void add_rules(struct ima_rule_entry *entries, int count, if (!entry) continue; - list_add_tail(&entry->list, &ima_policy_rules); + list_add_tail(&entry->list, &ns->ima_policy_rules); } if (entries[i].action == APPRAISE) { if (entries != build_appraise_rules) @@ -843,9 +841,10 @@ static void add_rules(struct ima_rule_entry *entries, int count, } } -static int ima_parse_rule(char *rule, struct ima_rule_entry *entry); +static int ima_parse_rule(struct ima_namespace *ns, + char *rule, struct ima_rule_entry *entry); -static int __init ima_init_arch_policy(void) +static int __init ima_init_arch_policy(struct ima_namespace *ns) { const char * const *arch_rules; const char * const *rules; @@ -873,7 +872,7 @@ static int __init ima_init_arch_policy(void) result = strscpy(rule, *rules, sizeof(rule)); INIT_LIST_HEAD(&arch_policy_entry[i].list); - result = ima_parse_rule(rule, &arch_policy_entry[i]); + result = ima_parse_rule(ns, rule, &arch_policy_entry[i]); if (result) { pr_warn("Skipping unknown architecture policy rule: %s\n", rule); @@ -891,23 +890,23 @@ static int __init ima_init_arch_policy(void) * * ima_rules points to either the ima_default_rules or the new ima_policy_rules. */ -void __init ima_init_policy(void) +void __init ima_init_policy(struct ima_namespace *ns) { int build_appraise_entries, arch_entries; /* if !ima_policy, we load NO default rules */ if (ima_policy) - add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules), + add_rules(ns, dont_measure_rules, ARRAY_SIZE(dont_measure_rules), IMA_DEFAULT_POLICY); switch (ima_policy) { case ORIGINAL_TCB: - add_rules(original_measurement_rules, + add_rules(ns, original_measurement_rules, ARRAY_SIZE(original_measurement_rules), IMA_DEFAULT_POLICY); break; case DEFAULT_TCB: - add_rules(default_measurement_rules, + add_rules(ns, default_measurement_rules, ARRAY_SIZE(default_measurement_rules), IMA_DEFAULT_POLICY); break; @@ -921,11 +920,11 @@ void __init ima_init_policy(void) * and custom policies, prior to other appraise rules. * (Highest priority) */ - arch_entries = ima_init_arch_policy(); + arch_entries = ima_init_arch_policy(ns); if (!arch_entries) pr_info("No architecture policies found\n"); else - add_rules(arch_policy_entry, arch_entries, + add_rules(ns, arch_policy_entry, arch_entries, IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); /* @@ -933,7 +932,7 @@ void __init ima_init_policy(void) * signatures, prior to other appraise rules. */ if (ima_use_secure_boot) - add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules), + add_rules(ns, secure_boot_rules, ARRAY_SIZE(secure_boot_rules), IMA_DEFAULT_POLICY); /* @@ -945,32 +944,32 @@ void __init ima_init_policy(void) build_appraise_entries = ARRAY_SIZE(build_appraise_rules); if (build_appraise_entries) { if (ima_use_secure_boot) - add_rules(build_appraise_rules, build_appraise_entries, + add_rules(ns, build_appraise_rules, build_appraise_entries, IMA_CUSTOM_POLICY); else - add_rules(build_appraise_rules, build_appraise_entries, + add_rules(ns, build_appraise_rules, build_appraise_entries, IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); } if (ima_use_appraise_tcb) - add_rules(default_appraise_rules, + add_rules(ns, default_appraise_rules, ARRAY_SIZE(default_appraise_rules), IMA_DEFAULT_POLICY); if (ima_use_critical_data) - add_rules(critical_data_rules, + add_rules(ns, critical_data_rules, ARRAY_SIZE(critical_data_rules), IMA_DEFAULT_POLICY); atomic_set(&ima_setxattr_allowed_hash_algorithms, 0); - ima_update_policy_flags(); + ima_update_policy_flags(ns); } /* Make sure we have a valid policy, at least containing some rules. */ -int ima_check_policy(void) +int ima_check_policy(struct ima_namespace *ns) { - if (list_empty(&ima_temp_rules)) + if (list_empty(&ns->ima_temp_rules)) return -EINVAL; return 0; } @@ -988,14 +987,14 @@ int ima_check_policy(void) */ void ima_update_policy(struct ima_namespace *ns) { - struct list_head *policy = &ima_policy_rules; + struct list_head *policy = &ns->ima_policy_rules; - list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); + list_splice_tail_init_rcu(&ns->ima_temp_rules, policy, synchronize_rcu); - if (ima_rules != (struct list_head __rcu *)policy) { - ima_policy_flag = 0; + if (ns->ima_rules != (struct list_head __rcu *)policy) { + ns->ima_policy_flag = 0; - rcu_assign_pointer(ima_rules, policy); + rcu_assign_pointer(ns->ima_rules, policy); /* * IMA architecture specific policy rules are specified * as strings and converted to an array of ima_entry_rules @@ -1004,7 +1003,7 @@ void ima_update_policy(struct ima_namespace *ns) */ kfree(arch_policy_entry); } - ima_update_policy_flags(); + ima_update_policy_flags(ns); /* Custom IMA policy has been loaded */ ima_process_queued_keys(ns); @@ -1077,7 +1076,8 @@ static const match_table_t policy_tokens = { {Opt_err, NULL} }; -static int ima_lsm_rule_init(struct ima_rule_entry *entry, +static int ima_lsm_rule_init(struct ima_namespace *ns, + struct ima_rule_entry *entry, substring_t *args, int lsm_rule, int audit_type) { int result; @@ -1097,7 +1097,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, pr_warn("rule for LSM \'%s\' is undefined\n", entry->lsm[lsm_rule].args_p); - if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) { + if (ns->ima_rules == (struct list_head __rcu *)(&ns->ima_default_rules)) { kfree(entry->lsm[lsm_rule].args_p); entry->lsm[lsm_rule].args_p = NULL; result = -EINVAL; @@ -1324,7 +1324,8 @@ static unsigned int ima_parse_appraise_algos(char *arg) return res; } -static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) +static int ima_parse_rule(struct ima_namespace *ns, + char *rule, struct ima_rule_entry *entry) { struct audit_buffer *ab; char *from; @@ -1674,37 +1675,37 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) break; case Opt_obj_user: ima_log_string(ab, "obj_user", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_OBJ_USER, AUDIT_OBJ_USER); break; case Opt_obj_role: ima_log_string(ab, "obj_role", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_OBJ_ROLE, AUDIT_OBJ_ROLE); break; case Opt_obj_type: ima_log_string(ab, "obj_type", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_OBJ_TYPE, AUDIT_OBJ_TYPE); break; case Opt_subj_user: ima_log_string(ab, "subj_user", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_SUBJ_USER, AUDIT_SUBJ_USER); break; case Opt_subj_role: ima_log_string(ab, "subj_role", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_SUBJ_ROLE, AUDIT_SUBJ_ROLE); break; case Opt_subj_type: ima_log_string(ab, "subj_type", args[0].from); - result = ima_lsm_rule_init(entry, args, + result = ima_lsm_rule_init(ns, entry, args, LSM_SUBJ_TYPE, AUDIT_SUBJ_TYPE); break; @@ -1810,7 +1811,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) * Avoid locking by allowing just one writer at a time in ima_write_policy() * Returns the length of the rule parsed, an error code on failure */ -ssize_t ima_parse_add_rule(char *rule) +ssize_t ima_parse_add_rule(struct ima_namespace *ns, char *rule) { static const char op[] = "update_policy"; char *p; @@ -1834,7 +1835,7 @@ ssize_t ima_parse_add_rule(char *rule) INIT_LIST_HEAD(&entry->list); - result = ima_parse_rule(p, entry); + result = ima_parse_rule(ns, p, entry); if (result) { ima_free_rule(entry); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, @@ -1843,7 +1844,7 @@ ssize_t ima_parse_add_rule(char *rule) return result; } - list_add_tail(&entry->list, &ima_temp_rules); + list_add_tail(&entry->list, &ns->ima_temp_rules); return len; } @@ -1854,12 +1855,24 @@ ssize_t ima_parse_add_rule(char *rule) * different from the active one. There is also only one user of * ima_delete_rules() at a time. */ -void ima_delete_rules(void) +void ima_delete_rules(struct ima_namespace *ns) { struct ima_rule_entry *entry, *tmp; temp_ima_appraise = 0; - list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { + list_for_each_entry_safe(entry, tmp, &ns->ima_temp_rules, list) { + list_del(&entry->list); + ima_free_rule(entry); + } +} + +void ima_free_policy_rules(struct ima_namespace *ns) +{ + struct ima_rule_entry *entry, *tmp; + + ima_delete_rules(ns); + + list_for_each_entry_safe(entry, tmp, &ns->ima_policy_rules, list) { list_del(&entry->list); ima_free_rule(entry); } @@ -1885,12 +1898,13 @@ static const char *const mask_tokens[] = { void *ima_policy_start(struct seq_file *m, loff_t *pos) { + struct ima_namespace *ns = get_current_ns(); loff_t l = *pos; struct ima_rule_entry *entry; struct list_head *ima_rules_tmp; rcu_read_lock(); - ima_rules_tmp = rcu_dereference(ima_rules); + ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) { if (!l--) { rcu_read_unlock(); @@ -1904,14 +1918,15 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) { struct ima_rule_entry *entry = v; + struct ima_namespace *ns = get_current_ns(); rcu_read_lock(); entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list); rcu_read_unlock(); (*pos)++; - return (&entry->list == &ima_default_rules || - &entry->list == &ima_policy_rules) ? NULL : entry; + return (&entry->list == &ns->ima_default_rules || + &entry->list == &ns->ima_policy_rules) ? NULL : entry; } void ima_policy_stop(struct seq_file *m, void *v) @@ -2166,6 +2181,7 @@ int ima_policy_show(struct seq_file *m, void *v) */ bool ima_appraise_signature(enum kernel_read_file_id id) { + struct ima_namespace *ns = get_current_ns(); struct ima_rule_entry *entry; bool found = false; enum ima_hooks func; @@ -2177,7 +2193,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id) func = read_idmap[id] ?: FILE_CHECK; rcu_read_lock(); - ima_rules_tmp = rcu_dereference(ima_rules); + ima_rules_tmp = rcu_dereference(ns->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) { if (entry->action != APPRAISE) continue; diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index 9e5e9a178253..14f334272160 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -142,7 +142,7 @@ void ima_process_queued_keys(struct ima_namespace *ns) list_for_each_entry_safe(entry, tmp, &ns->ima_keys, list) { if (!ns->timer_expired) - process_buffer_measurement(&init_user_ns, NULL, + process_buffer_measurement(ns, &init_user_ns, NULL, entry->payload, entry->payload_len, entry->keyring_name, From patchwork Fri Dec 10 19:47:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 025B7C433EF for ; Fri, 10 Dec 2021 19:47:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343705AbhLJTv2 (ORCPT ); Fri, 10 Dec 2021 14:51:28 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:63034 "EHLO mx0b-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242184AbhLJTv1 (ORCPT ); Fri, 10 Dec 2021 14:51:27 -0500 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAHoGQp015960; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=JYR4QsRzyY0N0JfGIc6zC7GQleBKavzXuIaeEuX3KqU=; b=WYKIBCsNVXJc9oQoDX74z/aS6Zbbchy4f3FbspkICzxjcPPLwE4wxFrHP1ktVecAeKYQ envcB+P+5fH+wsp5NYRvwMLx7tFnzj1CrXhw26FGyvIwODEJz17BzLkt5m9hI21pZ1Gg jXJ7wF5sHNNedBGeC095ZgfrQWTsE6azTgfW7LLB+J38TXmUP0C6dnirFfUHSCNO3Wb3 Kkc1dK0GeLNBjrXsht56jZjNAtUfPoJ3qUdK4eN90R3/70pkSg3J3n6zQeclNTf95oRq HJXFJVha1qozssODFuJdqSvrQ4rPaZH6NO/5vsXAbbC3/dBP63uYzqKspaU1miczMJgy Ig== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubgs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098421.ppops.net (m0098421.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJcv8g009235; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma03dal.us.ibm.com (b.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.11]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubge-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma03dal.us.ibm.com [127.0.0.1]) by ppma03dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJc5Rm020718; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma03dal.us.ibm.com with ESMTP id 3cqyydkvmc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlcWu54657444 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CF406AE064; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B0382AE068; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 07/17] ima: Move ima_htable into ima_namespace Date: Fri, 10 Dec 2021 14:47:26 -0500 Message-Id: <20211210194736.1538863-8-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: hqYbfunvQY_s1_ZeGNOpPQ5sv-bHb3nP X-Proofpoint-GUID: 57yPU8FV4czQJgjW8BXrkRXJ5OV4N7M4 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 phishscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 spamscore=0 mlxlogscore=999 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move ima_htable into ima_namespace. This way a front-end like SecurityFS can show the number of violations of an IMA namespace. Move ima_hash_key() into ima_queue.c since it's only used there. Signed-off-by: Stefan Berger --- include/linux/ima.h | 11 +++++++ security/integrity/ima/ima.h | 34 +++++++------------ security/integrity/ima/ima_api.c | 17 ++++++---- security/integrity/ima/ima_fs.c | 7 ++-- security/integrity/ima/ima_init.c | 6 ++-- security/integrity/ima/ima_init_ima_ns.c | 4 +++ security/integrity/ima/ima_kexec.c | 3 +- security/integrity/ima/ima_main.c | 13 ++++---- security/integrity/ima/ima_queue.c | 42 ++++++++++++++---------- security/integrity/ima/ima_template.c | 4 +-- 10 files changed, 80 insertions(+), 61 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 7a81e2d9fef0..65d28fa060c2 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -211,6 +211,15 @@ static inline int ima_inode_removexattr(struct dentry *dentry, } #endif /* CONFIG_IMA_APPRAISE */ +#define IMA_HASH_BITS 10 +#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) + +struct ima_h_table { + atomic_long_t len; /* number of stored measurements in the list */ + atomic_long_t violations; + struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; +}; + struct ima_namespace { struct rb_root ns_status_tree; rwlock_t ns_status_lock; @@ -246,6 +255,8 @@ struct ima_namespace { struct list_head __rcu *ima_rules; /* current content of the policy */ int ima_policy_flag; + + struct ima_h_table ima_htable; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index e295141f2478..a7e6c8fb152a 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -32,9 +32,6 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; #define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE #define IMA_EVENT_NAME_LEN_MAX 255 -#define IMA_HASH_BITS 10 -#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) - #define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16 #define IMA_TEMPLATE_NUM_FIELDS_MAX 15 @@ -143,7 +140,8 @@ struct ns_status { /* Internal IMA function definitions */ int ima_init(void); int ima_fs_init(void); -int ima_add_template_entry(struct ima_template_entry *entry, int violation, +int ima_add_template_entry(struct ima_namespace *ns, + struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename); int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); @@ -152,7 +150,8 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_entry *entry); int ima_calc_boot_aggregate(struct ima_digest_data *hash); -void ima_add_violation(struct file *file, const unsigned char *filename, +void ima_add_violation(struct ima_namespace *ns, + struct file *file, const unsigned char *filename, struct integrity_iint_cache *iint, const char *op, const char *cause); int ima_init_crypto(void); @@ -165,8 +164,10 @@ struct ima_template_desc *ima_template_desc_current(void); struct ima_template_desc *ima_template_desc_buf(void); struct ima_template_desc *lookup_template_desc(const char *name); bool ima_template_has_modsig(const struct ima_template_desc *ima_template); -int ima_restore_measurement_entry(struct ima_template_entry *entry); -int ima_restore_measurement_list(loff_t bufsize, void *buf); +int ima_restore_measurement_entry(struct ima_namespace *ns, + struct ima_template_entry *entry); +int ima_restore_measurement_list(struct ima_namespace *ns, + loff_t bufsize, void *buf); int ima_measurements_show(struct seq_file *m, void *v); unsigned long ima_get_binary_runtime_size(void); int ima_init_template(void); @@ -180,19 +181,6 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, */ extern spinlock_t ima_queue_lock; -struct ima_h_table { - atomic_long_t len; /* number of stored measurements in the list */ - atomic_long_t violations; - struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; -}; -extern struct ima_h_table ima_htable; - -static inline unsigned int ima_hash_key(u8 *digest) -{ - /* there is no point in taking a hash of part of a digest */ - return (digest[0] | digest[1] << 8) % IMA_MEASURE_HTABLE_SIZE; -} - #define __ima_hooks(hook) \ hook(NONE, none) \ hook(FILE_CHECK, file) \ @@ -272,7 +260,8 @@ int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file, void *buf, loff_t size, enum hash_algo algo, struct modsig *modsig); -void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, +void ima_store_measurement(struct ima_namespace *ns, + struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, @@ -289,7 +278,8 @@ void ima_audit_measurement(struct integrity_iint_cache *iint, int ima_alloc_init_template(struct ima_event_data *event_data, struct ima_template_entry **entry, struct ima_template_desc *template_desc); -int ima_store_template(struct ima_template_entry *entry, int violation, +int ima_store_template(struct ima_namespace *ns, + struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, int pcr); void ima_free_template_entry(struct ima_template_entry *entry); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 808aec56dbb6..71c5517fe8bc 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -100,7 +100,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data, * * Returns 0 on success, error code otherwise */ -int ima_store_template(struct ima_template_entry *entry, +int ima_store_template(struct ima_namespace *ns, + struct ima_template_entry *entry, int violation, struct inode *inode, const unsigned char *filename, int pcr) { @@ -120,7 +121,7 @@ int ima_store_template(struct ima_template_entry *entry, } } entry->pcr = pcr; - result = ima_add_template_entry(entry, violation, op, inode, filename); + result = ima_add_template_entry(ns, entry, violation, op, inode, filename); return result; } @@ -131,7 +132,8 @@ int ima_store_template(struct ima_template_entry *entry, * By extending the PCR with 0xFF's instead of with zeroes, the PCR * value is invalidated. */ -void ima_add_violation(struct file *file, const unsigned char *filename, +void ima_add_violation(struct ima_namespace *ns, + struct file *file, const unsigned char *filename, struct integrity_iint_cache *iint, const char *op, const char *cause) { @@ -145,14 +147,14 @@ void ima_add_violation(struct file *file, const unsigned char *filename, int result; /* can overflow, only indicator */ - atomic_long_inc(&ima_htable.violations); + atomic_long_inc(&ns->ima_htable.violations); result = ima_alloc_init_template(&event_data, &entry, NULL); if (result < 0) { result = -ENOMEM; goto err_out; } - result = ima_store_template(entry, violation, inode, + result = ima_store_template(ns, entry, violation, inode, filename, CONFIG_IMA_MEASURE_PCR_IDX); if (result < 0) ima_free_template_entry(entry); @@ -299,7 +301,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, * * Must be called with iint->mutex held. */ -void ima_store_measurement(struct integrity_iint_cache *iint, +void ima_store_measurement(struct ima_namespace *ns, + struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, const struct modsig *modsig, int pcr, @@ -334,7 +337,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, return; } - result = ima_store_template(entry, violation, inode, filename, pcr); + result = ima_store_template(ns, entry, violation, inode, filename, pcr); if ((!result || result == -EEXIST) && !(file->f_flags & O_DIRECT)) { iint->flags |= IMA_MEASURED; iint->measured_pcrs |= (0x1 << pcr); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 25f85c58ebef..e37c973a94c6 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -53,7 +53,9 @@ static ssize_t ima_show_htable_violations(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - return ima_show_htable_value(buf, count, ppos, &ima_htable.violations); + struct ima_namespace *ns = get_current_ns(); + + return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.violations); } static const struct file_operations ima_htable_violations_ops = { @@ -65,8 +67,9 @@ static ssize_t ima_show_measurements_count(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - return ima_show_htable_value(buf, count, ppos, &ima_htable.len); + struct ima_namespace *ns = get_current_ns(); + return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.len); } static const struct file_operations ima_measurements_count_ops = { diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index d78f8faf6dcd..8e0ae3a4f04a 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -39,7 +39,7 @@ struct tpm_chip *ima_tpm_chip; * a different value.) Violations add a zero entry to the measurement * list and extend the aggregate PCR value with ff...ff's. */ -static int __init ima_add_boot_aggregate(void) +static int __init ima_add_boot_aggregate(struct ima_namespace *ns) { static const char op[] = "add_boot_aggregate"; const char *audit_cause = "ENOMEM"; @@ -86,7 +86,7 @@ static int __init ima_add_boot_aggregate(void) goto err_out; } - result = ima_store_template(entry, violation, NULL, + result = ima_store_template(ns, entry, violation, NULL, boot_aggregate_name, CONFIG_IMA_MEASURE_PCR_IDX); if (result < 0) { @@ -145,7 +145,7 @@ int __init ima_init(void) rc = ima_init_digests(); if (rc != 0) return rc; - rc = ima_add_boot_aggregate(); /* boot aggregate must be first entry */ + rc = ima_add_boot_aggregate(&init_ima_ns); /* boot aggregate must be first entry */ if (rc != 0) return rc; diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index db7de6811fcc..02aa7db4c617 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -40,6 +40,10 @@ int ima_init_namespace(struct ima_namespace *ns) ns->ima_rules = (struct list_head __rcu *)(&ns->ima_default_rules); ns->ima_policy_flag = 0; + atomic_long_set(&ns->ima_htable.len, 0); + atomic_long_set(&ns->ima_htable.violations, 0); + memset(&ns->ima_htable.queue, 0, sizeof(ns->ima_htable.queue)); + return 0; } diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index f799cc278a9a..f3ef8a0df992 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -146,7 +146,8 @@ void ima_load_kexec_buffer(void) rc = ima_get_kexec_buffer(&kexec_buffer, &kexec_buffer_size); switch (rc) { case 0: - rc = ima_restore_measurement_list(kexec_buffer_size, + rc = ima_restore_measurement_list(&init_ima_ns, + kexec_buffer_size, kexec_buffer); if (rc != 0) pr_err("Failed to restore the measurement list: %d\n", diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 897304046ba4..2121a831f38a 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -112,7 +112,8 @@ static int mmap_violation_check(enum ima_hooks func, struct file *file, * could result in a file measurement error. * */ -static void ima_rdwr_violation_check(struct file *file, +static void ima_rdwr_violation_check(struct ima_namespace *ns, + struct file *file, struct integrity_iint_cache *iint, int must_measure, char **pathbuf, @@ -145,10 +146,10 @@ static void ima_rdwr_violation_check(struct file *file, *pathname = ima_d_path(&file->f_path, pathbuf, filename); if (send_tomtou) - ima_add_violation(file, *pathname, iint, + ima_add_violation(ns, file, *pathname, iint, "invalid_pcr", "ToMToU"); if (send_writers) - ima_add_violation(file, *pathname, iint, + ima_add_violation(ns, file, *pathname, iint, "invalid_pcr", "open_writers"); } @@ -257,7 +258,7 @@ static int process_measurement(struct ima_namespace *ns, } if (!rc && violation_check) - ima_rdwr_violation_check(file, iint, action & IMA_MEASURE, + ima_rdwr_violation_check(ns, file, iint, action & IMA_MEASURE, &pathbuf, &pathname, filename); inode_unlock(inode); @@ -354,7 +355,7 @@ static int process_measurement(struct ima_namespace *ns, pathname = ima_d_path(&file->f_path, &pathbuf, filename); if (action & IMA_MEASURE) - ima_store_measurement(iint, file, pathname, + ima_store_measurement(ns, iint, file, pathname, xattr_value, xattr_len, modsig, pcr, template_desc); if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { @@ -978,7 +979,7 @@ int process_buffer_measurement(struct ima_namespace *ns, goto out; } - ret = ima_store_template(entry, violation, NULL, event_data.buf, pcr); + ret = ima_store_template(ns, entry, violation, NULL, event_data.buf, pcr); if (ret < 0) { audit_cause = "store_entry"; ima_free_template_entry(entry); diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 532da87ce519..373154039b91 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -17,6 +17,7 @@ #include #include +#include #include "ima.h" #define AUDIT_CAUSE_LEN_MAX 32 @@ -31,21 +32,22 @@ static unsigned long binary_runtime_size; static unsigned long binary_runtime_size = ULONG_MAX; #endif -/* key: inode (before secure-hashing a file) */ -struct ima_h_table ima_htable = { - .len = ATOMIC_LONG_INIT(0), - .violations = ATOMIC_LONG_INIT(0), - .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT -}; - /* mutex protects atomicity of extending measurement list * and extending the TPM PCR aggregate. Since tpm_extend can take * long (and the tpm driver uses a mutex), we can't use the spinlock. */ static DEFINE_MUTEX(ima_extend_list_mutex); + +static inline unsigned int ima_hash_key(u8 *digest) +{ + /* there is no point in taking a hash of part of a digest */ + return (digest[0] | digest[1] << 8) % IMA_MEASURE_HTABLE_SIZE; +} + /* lookup up the digest value in the hash table, and return the entry */ -static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, +static struct ima_queue_entry *ima_lookup_digest_entry(struct ima_namespace *ns, + u8 *digest_value, int pcr) { struct ima_queue_entry *qe, *ret = NULL; @@ -54,7 +56,7 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, key = ima_hash_key(digest_value); rcu_read_lock(); - hlist_for_each_entry_rcu(qe, &ima_htable.queue[key], hnext) { + hlist_for_each_entry_rcu(qe, &ns->ima_htable.queue[key], hnext) { rc = memcmp(qe->entry->digests[ima_hash_algo_idx].digest, digest_value, hash_digest_size[ima_hash_algo]); if ((rc == 0) && (qe->entry->pcr == pcr)) { @@ -90,7 +92,8 @@ static int get_binary_runtime_size(struct ima_template_entry *entry) * * (Called with ima_extend_list_mutex held.) */ -static int ima_add_digest_entry(struct ima_template_entry *entry, +static int ima_add_digest_entry(struct ima_namespace *ns, + struct ima_template_entry *entry, bool update_htable) { struct ima_queue_entry *qe; @@ -106,11 +109,12 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, INIT_LIST_HEAD(&qe->later); list_add_tail_rcu(&qe->later, &ima_measurements); - atomic_long_inc(&ima_htable.len); + atomic_long_inc(&ns->ima_htable.len); if (update_htable) { key = ima_hash_key(entry->digests[ima_hash_algo_idx].digest); - hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); - } + hlist_add_head_rcu(&qe->hnext, &ns->ima_htable.queue[key]); + } else + INIT_HLIST_NODE(&qe->hnext); if (binary_runtime_size != ULONG_MAX) { int size; @@ -156,7 +160,8 @@ static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) * kexec, maintain the total memory size required for serializing the * binary_runtime_measurements. */ -int ima_add_template_entry(struct ima_template_entry *entry, int violation, +int ima_add_template_entry(struct ima_namespace *ns, + struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename) { @@ -169,14 +174,14 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, mutex_lock(&ima_extend_list_mutex); if (!violation && !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)) { - if (ima_lookup_digest_entry(digest, entry->pcr)) { + if (ima_lookup_digest_entry(ns, digest, entry->pcr)) { audit_cause = "hash_exists"; result = -EEXIST; goto out; } } - result = ima_add_digest_entry(entry, + result = ima_add_digest_entry(ns, entry, !IS_ENABLED(CONFIG_IMA_DISABLE_HTABLE)); if (result < 0) { audit_cause = "ENOMEM"; @@ -201,12 +206,13 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, return result; } -int ima_restore_measurement_entry(struct ima_template_entry *entry) +int ima_restore_measurement_entry(struct ima_namespace *ns, + struct ima_template_entry *entry) { int result = 0; mutex_lock(&ima_extend_list_mutex); - result = ima_add_digest_entry(entry, 0); + result = ima_add_digest_entry(ns, entry, 0); mutex_unlock(&ima_extend_list_mutex); return result; } diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 694560396be0..2ae87eb23a59 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -400,7 +400,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc, } /* Restore the serialized binary measurement list without extending PCRs. */ -int ima_restore_measurement_list(loff_t size, void *buf) +int ima_restore_measurement_list(struct ima_namespace *ns, loff_t size, void *buf) { char template_name[MAX_TEMPLATE_NAME_LEN]; unsigned char zero[TPM_DIGEST_SIZE] = { 0 }; @@ -516,7 +516,7 @@ int ima_restore_measurement_list(loff_t size, void *buf) entry->pcr = !ima_canonical_fmt ? *(u32 *)(hdr[HDR_PCR].data) : le32_to_cpu(*(__le32 *)(hdr[HDR_PCR].data)); - ret = ima_restore_measurement_entry(entry); + ret = ima_restore_measurement_entry(ns, entry); if (ret < 0) break; From patchwork Fri Dec 10 19:47:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670825 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69523C43219 for ; Fri, 10 Dec 2021 19:48:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242834AbhLJTvf (ORCPT ); Fri, 10 Dec 2021 14:51:35 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:31612 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343709AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAIvnNb030621; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=v4jXZ9HfkyO2KRevHrMwH6PzIw1SUEa0p3T2Yes9zbg=; b=S+/BluZ2NEQ2J/eUwkB+XvTcqkGmGDCi4yNqYne6vl3t1AioPLwbjqSITJxa1DT/MbpH yLOZtU5BvDTxOiu5VhSeyuMrRDo71PlGEK661YsQDnnyTzEHvIr3ILPPAKp1ZXommK12 E0nJUNyLEWYWXnBdYgucVuYh37f6TO9BeHZhKpGseLP2kZm5rmbhV/HfsTFY3UaUVLQt wq5/1kLT4WY2MBUl65l8jj05qK1KIJ4LB1BtCKw8F1wOQtxIO/uhlS1IzdhsVjvpBF8s L/1rqDNYCTUY6B35HTSwlbWIN6AQ3Sm48KtytlSnQ4YvScFcyYRZ1hskxu/pZ8ABS/a4 +A== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvcms903v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098419.ppops.net (m0098419.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJRK6H008781; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvcms903q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcOZW001962; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma04dal.us.ibm.com with ESMTP id 3cqyydbsqb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldST31719732 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ECC78AE066; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D857BAE06A; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 08/17] ima: Move measurement list related variables into ima_namespace Date: Fri, 10 Dec 2021 14:47:27 -0500 Message-Id: <20211210194736.1538863-9-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: PD9DNR4Vqn7aoDZ2IIUug21_Y2eFyhan X-Proofpoint-GUID: f7qiUjYMEfsO6WXwQRTQ0gkVHiAXON0h X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 mlxscore=0 phishscore=0 spamscore=0 malwarescore=0 mlxlogscore=999 priorityscore=1501 suspectscore=0 adultscore=0 clxscore=1015 bulkscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move measurement list related variables into the ima_namespace. This way a front-end like SecurityFS can show the measurement list inside an IMA namespace. Implement ima_free_measurements() to free a list of measurements and call it when an IMA namespace is deleted. Signed-off-by: Stefan Berger --- include/linux/ima.h | 2 ++ security/integrity/ima/ima.h | 4 +-- security/integrity/ima/ima_fs.c | 6 +++-- security/integrity/ima/ima_init_ima_ns.c | 5 ++++ security/integrity/ima/ima_kexec.c | 12 +++++---- security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_queue.c | 33 ++++++++++++++---------- 7 files changed, 40 insertions(+), 23 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 65d28fa060c2..85903f40acfd 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -257,6 +257,8 @@ struct ima_namespace { int ima_policy_flag; struct ima_h_table ima_htable; + struct list_head ima_measurements; + unsigned long binary_runtime_size; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index a7e6c8fb152a..bb9763cd5fb1 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -104,7 +104,6 @@ struct ima_queue_entry { struct list_head later; /* place in ima_measurements list */ struct ima_template_entry *entry; }; -extern struct list_head ima_measurements; /* list of all measurements */ /* Some details preceding the binary serialized measurement list */ struct ima_kexec_hdr { @@ -168,8 +167,9 @@ int ima_restore_measurement_entry(struct ima_namespace *ns, struct ima_template_entry *entry); int ima_restore_measurement_list(struct ima_namespace *ns, loff_t bufsize, void *buf); +void ima_free_measurements(struct ima_namespace *ns); int ima_measurements_show(struct seq_file *m, void *v); -unsigned long ima_get_binary_runtime_size(void); +unsigned long ima_get_binary_runtime_size(struct ima_namespace *ns); int ima_init_template(void); void ima_init_template_list(void); int __init ima_init_digests(void); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index e37c973a94c6..38b1c26479b3 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -80,12 +80,13 @@ static const struct file_operations ima_measurements_count_ops = { /* returns pointer to hlist_node */ static void *ima_measurements_start(struct seq_file *m, loff_t *pos) { + struct ima_namespace *ns = get_current_ns(); loff_t l = *pos; struct ima_queue_entry *qe; /* we need a lock since pos could point beyond last element */ rcu_read_lock(); - list_for_each_entry_rcu(qe, &ima_measurements, later) { + list_for_each_entry_rcu(qe, &ns->ima_measurements, later) { if (!l--) { rcu_read_unlock(); return qe; @@ -97,6 +98,7 @@ static void *ima_measurements_start(struct seq_file *m, loff_t *pos) static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) { + struct ima_namespace *ns = get_current_ns(); struct ima_queue_entry *qe = v; /* lock protects when reading beyond last element @@ -107,7 +109,7 @@ static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) rcu_read_unlock(); (*pos)++; - return (&qe->later == &ima_measurements) ? NULL : qe; + return (&qe->later == &ns->ima_measurements) ? NULL : qe; } static void ima_measurements_stop(struct seq_file *m, void *v) diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index 02aa7db4c617..3bec9a2a0bd9 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -43,6 +43,11 @@ int ima_init_namespace(struct ima_namespace *ns) atomic_long_set(&ns->ima_htable.len, 0); atomic_long_set(&ns->ima_htable.violations, 0); memset(&ns->ima_htable.queue, 0, sizeof(ns->ima_htable.queue)); + INIT_LIST_HEAD(&ns->ima_measurements); + if (IS_ENABLED(CONFIG_IMA_KEXEC) && ns == &init_ima_ns) + ns->binary_runtime_size = 0; + else + ns->binary_runtime_size = ULONG_MAX; return 0; } diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index f3ef8a0df992..c07149228013 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -15,7 +15,8 @@ #include "ima.h" #ifdef CONFIG_IMA_KEXEC -static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer, +static int ima_dump_measurement_list(struct ima_namespace *ns, + unsigned long *buffer_size, void **buffer, unsigned long segment_size) { struct ima_queue_entry *qe; @@ -36,7 +37,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer, memset(&khdr, 0, sizeof(khdr)); khdr.version = 1; - list_for_each_entry_rcu(qe, &ima_measurements, later) { + list_for_each_entry_rcu(qe, &ns->ima_measurements, later) { if (file.count < file.size) { khdr.count++; ima_measurements_show(&file, qe); @@ -84,6 +85,7 @@ void ima_add_kexec_buffer(struct kimage *image) struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE, .buf_min = 0, .buf_max = ULONG_MAX, .top_down = true }; + struct ima_namespace *ns = &init_ima_ns; unsigned long binary_runtime_size; /* use more understandable variable names than defined in kbuf */ @@ -96,11 +98,11 @@ void ima_add_kexec_buffer(struct kimage *image) * Reserve an extra half page of memory for additional measurements * added during the kexec load. */ - binary_runtime_size = ima_get_binary_runtime_size(); + binary_runtime_size = ima_get_binary_runtime_size(ns); if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE) kexec_segment_size = ULONG_MAX; else - kexec_segment_size = ALIGN(ima_get_binary_runtime_size() + + kexec_segment_size = ALIGN(ima_get_binary_runtime_size(ns) + PAGE_SIZE / 2, PAGE_SIZE); if ((kexec_segment_size == ULONG_MAX) || ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) { @@ -108,7 +110,7 @@ void ima_add_kexec_buffer(struct kimage *image) return; } - ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer, + ima_dump_measurement_list(ns, &kexec_buffer_size, &kexec_buffer, kexec_segment_size); if (!kexec_buffer) { pr_err("Not enough memory for the kexec measurement buffer.\n"); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 9d97f45fa8e4..97596282e7bc 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -56,6 +56,7 @@ static void destroy_ima_ns(struct ima_namespace *ns) pr_debug("DESTROY ima_ns: 0x%p\n", ns); ima_free_policy_rules(ns); free_ns_status_cache(ns); + ima_free_measurements(ns); kmem_cache_free(imans_cachep, ns); } diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 373154039b91..f15f776918ec 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -25,13 +25,6 @@ /* pre-allocated array of tpm_digest structures to extend a PCR */ static struct tpm_digest *digests; -LIST_HEAD(ima_measurements); /* list of all measurements */ -#ifdef CONFIG_IMA_KEXEC -static unsigned long binary_runtime_size; -#else -static unsigned long binary_runtime_size = ULONG_MAX; -#endif - /* mutex protects atomicity of extending measurement list * and extending the TPM PCR aggregate. Since tpm_extend can take * long (and the tpm driver uses a mutex), we can't use the spinlock. @@ -107,7 +100,7 @@ static int ima_add_digest_entry(struct ima_namespace *ns, qe->entry = entry; INIT_LIST_HEAD(&qe->later); - list_add_tail_rcu(&qe->later, &ima_measurements); + list_add_tail_rcu(&qe->later, &ns->ima_measurements); atomic_long_inc(&ns->ima_htable.len); if (update_htable) { @@ -116,12 +109,12 @@ static int ima_add_digest_entry(struct ima_namespace *ns, } else INIT_HLIST_NODE(&qe->hnext); - if (binary_runtime_size != ULONG_MAX) { + if (ns->binary_runtime_size != ULONG_MAX) { int size; size = get_binary_runtime_size(entry); - binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ? - binary_runtime_size + size : ULONG_MAX; + ns->binary_runtime_size = (ns->binary_runtime_size < ULONG_MAX - size) ? + ns->binary_runtime_size + size : ULONG_MAX; } return 0; } @@ -131,12 +124,12 @@ static int ima_add_digest_entry(struct ima_namespace *ns, * entire binary_runtime_measurement list, including the ima_kexec_hdr * structure. */ -unsigned long ima_get_binary_runtime_size(void) +unsigned long ima_get_binary_runtime_size(struct ima_namespace *ns) { - if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr))) + if (ns->binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr))) return ULONG_MAX; else - return binary_runtime_size + sizeof(struct ima_kexec_hdr); + return ns->binary_runtime_size + sizeof(struct ima_kexec_hdr); } static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) @@ -217,6 +210,18 @@ int ima_restore_measurement_entry(struct ima_namespace *ns, return result; } +void ima_free_measurements(struct ima_namespace *ns) +{ + struct ima_queue_entry *qe, *tmp; + + list_for_each_entry_safe(qe, tmp, &ns->ima_measurements, later) { + list_del(&qe->later); + if (!hlist_unhashed(&qe->hnext)) + hlist_del(&qe->hnext); + kfree(qe); + } +} + int __init ima_init_digests(void) { u16 digest_size; From patchwork Fri Dec 10 19:47:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670831 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3300DC433EF for ; Fri, 10 Dec 2021 19:48:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343874AbhLJTvq (ORCPT ); Fri, 10 Dec 2021 14:51:46 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:22054 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343835AbhLJTvn (ORCPT ); Fri, 10 Dec 2021 14:51:43 -0500 Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJBY4t028246; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=Z69muX35ZlpobS3w1nUqcim7JCLDXKuabnrT4KTs25c=; b=aBUXKtrwXXYFAoF1Knw+YYcJvIJYDXC/LI8WTb4QKn/3LArteP/umtwI4yoUO2zh2+wP 7HZH3HE3xkZeLFWKipDcGdGtixFeG1t6OJ49unJ4y1J+eu7ZuPgK81K9VzEIjg44WNdo et9NjlBzJIog+DnnCvraXyFvsiq5gX2aoAobzXQlnGpSkFBa31miRbdwjL1iPnNp+cIY RFdTTADUlGy4+2t5wsVh9hiw6lNnQFrEQLzbAFFq/WlTejIwryYtVSLpL/iv4UXD+IE9 4nXOhL+c92zUjbWLWLA+dcVTjRh+tDS1ylHxqMzdUpDhTHbGjNHdob6SrAQ8oVzWDXOm tQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvcu6rjxs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098399.ppops.net (m0098399.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJlfb2010708; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvcu6rjx8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcOZV001962; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma04dal.us.ibm.com with ESMTP id 3cqyydbsqa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldZS25231670 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 17025AE060; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 02E9FAE076; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:38 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 09/17] ima: Only accept AUDIT rules for IMA non-init_ima_ns namespaces for now Date: Fri, 10 Dec 2021 14:47:28 -0500 Message-Id: <20211210194736.1538863-10-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: kujcZSS8lAy4crCAUBig9FWpfX58L7KB X-Proofpoint-ORIG-GUID: AaB_DCsiVxGL0RIr0s-cmAPGU_cxypru X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 lowpriorityscore=0 impostorscore=0 adultscore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 suspectscore=0 spamscore=0 mlxscore=0 phishscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Only accept AUDIT rules for non-init_ima_ns namespaces rejecting all rules that require support for measuring, appraisal, and hashing. Signed-off-by: Stefan Berger --- security/integrity/ima/ima_policy.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 4d6d3a39f65e..747dca6131d6 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1787,6 +1787,16 @@ static int ima_parse_rule(struct ima_namespace *ns, result = -EINVAL; break; } + + /* IMA namespace only accepts AUDIT rules */ + if (ns != &init_ima_ns) { + switch (entry->action) { + case MEASURE: + case APPRAISE: + case HASH: + result = -EINVAL; + } + } } if (!result && !ima_validate_rule(entry)) result = -EINVAL; From patchwork Fri Dec 10 19:47:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670839 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 502BFC433FE for ; Fri, 10 Dec 2021 19:48:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343723AbhLJTvw (ORCPT ); Fri, 10 Dec 2021 14:51:52 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:48442 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343784AbhLJTvn (ORCPT ); Fri, 10 Dec 2021 14:51:43 -0500 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAI873k011051; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=9RmU5lKfZ5PEbMv5qG3TyQvw1FSleHbq6OtkG5qdlvU=; b=AxUdt87o0TYUFGirU2YFYtt4KB7+dOtGwSu3W7gEGOvfcRQk3Zl6gmoYTXS182GXcI4Z jYHzI+zk6i+BKrYENSgOAcNjxAd9jFMh4GI35NXGV2XP8o3hbd5Z6tE6DCFjDpg6/30P Sa2/D3PUL3m1dHvvXt5hgAcyNCsFxvsKB+3KvbWZc90I46acPDYHMUnOkoNB0MpowCe4 cU1s6va7uLBLLA1XE5uPlF0zoRYBkAP0ZQZd5Ba/P+q5U7zuri7l/sUxOdKFjyyRemJH 90qJ0TJFRHlN2z5JGReMXdlL67O9VLZawXTJmNX4jYHTKMLhsi8GdNorYHyQc4HuHy8L BA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjcd6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098394.ppops.net (m0098394.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJaEUR017223; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma02dal.us.ibm.com (a.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.10]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvbatjccq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma02dal.us.ibm.com [127.0.0.1]) by ppma02dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJlIQd029473; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma02dal.us.ibm.com with ESMTP id 3cqyydm09e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldRD22610394 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3136EAE067; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1FD78AE071; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 10/17] ima: Implement hierarchical processing of file accesses Date: Fri, 10 Dec 2021 14:47:29 -0500 Message-Id: <20211210194736.1538863-11-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: 8RCH_TY1yDOeMePp04PF3cWZ_lfsPnky X-Proofpoint-GUID: b0zkdrDhrIjxNPfxpZYdSBciGEoYLHx0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 phishscore=0 spamscore=0 suspectscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 clxscore=1015 adultscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Implement hierarchical processing of file accesses in IMA namespaces by walking the list of IMA namespaces towards the init_ima_ns. This way file accesses can be audited in an IMA namespace and also be evaluated against the IMA policies of parent IMA namespaces. Signed-off-by: Stefan Berger --- include/linux/ima.h | 9 +++++++++ security/integrity/ima/ima_main.c | 29 +++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 85903f40acfd..fda371cbde50 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -66,6 +66,15 @@ static inline const char * const *arch_get_ima_policy(void) } #endif +static inline struct user_namespace *ima_user_ns(struct ima_namespace *ns) +{ + struct user_namespace *user_ns; + + user_ns = current_user_ns(); + WARN_ON(user_ns->ima_ns != ns); + return user_ns; +} + #else static inline enum hash_algo ima_get_current_hash_algo(void) { diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2121a831f38a..6ebc57cd91d3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -200,10 +200,10 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } -static int process_measurement(struct ima_namespace *ns, - struct file *file, const struct cred *cred, - u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func) +static int __process_measurement(struct ima_namespace *ns, + struct file *file, const struct cred *cred, + u32 secid, char *buf, loff_t size, int mask, + enum ima_hooks func) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -405,6 +405,27 @@ static int process_measurement(struct ima_namespace *ns, return 0; } +static int process_measurement(struct ima_namespace *ns, + struct file *file, const struct cred *cred, + u32 secid, char *buf, loff_t size, int mask, + enum ima_hooks func) +{ + struct user_namespace *user_ns = ima_user_ns(ns); + int ret = 0; + + while (user_ns) { + ns = user_ns->ima_ns; + + ret = __process_measurement(ns, file, cred, secid, buf, size, mask, func); + if (ret) + break; + + user_ns = user_ns->parent; + }; + + return ret; +} + /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) From patchwork Fri Dec 10 19:47:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670819 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9748EC433EF for ; Fri, 10 Dec 2021 19:47:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343737AbhLJTvd (ORCPT ); Fri, 10 Dec 2021 14:51:33 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:25740 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343712AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJSXus006400; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=970NtxA2esXJGJboDzZrD3TQdgR+7LQwSe1pqIrYBbk=; b=m3JIiBsUlIo/7NwYnD5S796C/UB6ZYKvFvYUCw6sGVyPy2ZINEHUkXHDt8xNtcgyF1oa /KoadssJi3IScYN4DNgS4IhehYdDH+l/wuPYv1h3xZefCB0aKFNonp6pCHJvKmcJseAh lG5JZf04Q/A43ndnJw3zpqXYjICZ5oMmBjW1p4L7W0HN4huLvgEjw7Zws/Cnn20yDTnj Tt6kVuaZV4GQcWAVwhZ3XLoTCKrLjmyYb6LzPDG2+LDW1p/P8fsy173THOugEZbgsKUO T0TccDfz8qzHfq707Y3oKMFFZMVOwacle+cmbslokDojSvqI6iO29Yhf6f+vX7sONiN0 Cg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd370a10-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0098413.ppops.net (m0098413.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJg9ro029170; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma03wdc.us.ibm.com (ba.79.3fa9.ip4.static.sl-reverse.com [169.63.121.186]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd370a0s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma03wdc.us.ibm.com [127.0.0.1]) by ppma03wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcScK006979; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma03wdc.us.ibm.com with ESMTP id 3cqyy9wu0u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldZN27132358 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4FBA8AE066; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3C3C5AE076; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , James Bottomley Subject: [PATCH v6 11/17] securityfs: Only use simple_pin_fs/simple_release_fs for init_user_ns Date: Fri, 10 Dec 2021 14:47:30 -0500 Message-Id: <20211210194736.1538863-12-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: 87CusPLSDDIv-9HaBcL21yV1vuMhE7tp X-Proofpoint-GUID: EZaHEQ0-gjLZ54tKLN4NTTrFdbz3bhv8 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 clxscore=1015 mlxscore=0 malwarescore=0 spamscore=0 bulkscore=0 impostorscore=0 mlxlogscore=999 phishscore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: To prepare for virtualization of SecurityFS, use simple_pin_fs and simpe_release_fs only when init_user_ns is active. Signed-off-by: Stefan Berger Signed-off-by: James Bottomley Acked-by: Christian Brauner --- security/inode.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/security/inode.c b/security/inode.c index 6c326939750d..fee01ff4d831 100644 --- a/security/inode.c +++ b/security/inode.c @@ -21,9 +21,10 @@ #include #include #include +#include -static struct vfsmount *mount; -static int mount_count; +static struct vfsmount *init_securityfs_mount; +static int init_securityfs_mount_count; static void securityfs_free_inode(struct inode *inode) { @@ -109,6 +110,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, const struct file_operations *fops, const struct inode_operations *iops) { + struct user_namespace *ns = current_user_ns(); struct dentry *dentry; struct inode *dir, *inode; int error; @@ -118,12 +120,19 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, pr_debug("securityfs: creating file '%s'\n",name); - error = simple_pin_fs(&fs_type, &mount, &mount_count); - if (error) - return ERR_PTR(error); + if (ns == &init_user_ns) { + error = simple_pin_fs(&fs_type, &init_securityfs_mount, + &init_securityfs_mount_count); + if (error) + return ERR_PTR(error); + } - if (!parent) - parent = mount->mnt_root; + if (!parent) { + if (ns == &init_user_ns) + parent = init_securityfs_mount->mnt_root; + else + return ERR_PTR(-EINVAL); + } dir = d_inode(parent); @@ -168,7 +177,9 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, dentry = ERR_PTR(error); out: inode_unlock(dir); - simple_release_fs(&mount, &mount_count); + if (ns == &init_user_ns) + simple_release_fs(&init_securityfs_mount, + &init_securityfs_mount_count); return dentry; } @@ -294,11 +305,14 @@ EXPORT_SYMBOL_GPL(securityfs_create_symlink); */ void securityfs_remove(struct dentry *dentry) { + struct user_namespace *ns; struct inode *dir; if (!dentry || IS_ERR(dentry)) return; + ns = dentry->d_sb->s_user_ns; + dir = d_inode(dentry->d_parent); inode_lock(dir); if (simple_positive(dentry)) { @@ -309,7 +323,9 @@ void securityfs_remove(struct dentry *dentry) dput(dentry); } inode_unlock(dir); - simple_release_fs(&mount, &mount_count); + if (ns == &init_user_ns) + simple_release_fs(&init_securityfs_mount, + &init_securityfs_mount_count); } EXPORT_SYMBOL_GPL(securityfs_remove); From patchwork Fri Dec 10 19:47:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670833 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 916ECC433F5 for ; Fri, 10 Dec 2021 19:48:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343897AbhLJTvs (ORCPT ); Fri, 10 Dec 2021 14:51:48 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:57162 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343839AbhLJTvo (ORCPT ); Fri, 10 Dec 2021 14:51:44 -0500 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJfbr4003784; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=T0p8yQkb5het3/69uVSEvEhiCwN07UUzs4owyWuTuf8=; b=M2p7CePiS4DAmBSVMRSRAwm5IZO234MgobUJ1itcqlB967N0ifD/gswSh0QVVY8rnWyZ De1xUR+cMlRot6M1JytCyWOL5gkMdTiN7KoxlFBl514uxlnK9aiY0mc1O4lPyYHjvcJv WE1XzlBlzuZUgFTCZySMdvG8A/k7D2vAOsXT6Q6P/XI+0/CyRlfQ95uVszrdeuAZD79q NK/Ez+FfJ9GMrBvRgZsSVbs+iIzj83pbMX0UtYtDvFQ1f6OXRFytkktNWBfjmKhIM6Ts 4ZJMdNDaGKZnKinT+lj5Me3FuBC0BKdOoj2LuHxRq9dP0gdN99MVJL3S27EfcLraVL+9 fw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvd97r2qp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJlgXn027292; Fri, 10 Dec 2021 19:47:42 GMT Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvd97r2qb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJchee013159; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma01wdc.us.ibm.com with ESMTP id 3cqyycnqk0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJld6n29753826 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6CD8BAE067; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5ABD5AE068; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , James Bottomley Subject: [PATCH v6 12/17] securityfs: Extend securityfs with namespacing support Date: Fri, 10 Dec 2021 14:47:31 -0500 Message-Id: <20211210194736.1538863-13-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: yncE3-5-nmbwVC_TY2vqF6NCf808KFlR X-Proofpoint-ORIG-GUID: gy02mhljES78at2VC1PcId8HQy6zn44N X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 impostorscore=0 adultscore=0 mlxscore=0 spamscore=0 malwarescore=0 mlxlogscore=999 bulkscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Extend 'securityfs' for support of IMA namespacing so that each IMA (user) namespace can have its own front-end for showing the currently active policy, the measurement list, number of violations and so on. Drop the addition dentry reference and simplify cleanup to work without the additional reference. This enables simple cleanup of dentries upon umount. Signed-off-by: Stefan Berger Signed-off-by: James Bottomley --- security/inode.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/security/inode.c b/security/inode.c index fee01ff4d831..c77ae8ecc464 100644 --- a/security/inode.c +++ b/security/inode.c @@ -54,7 +54,7 @@ static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc) static int securityfs_get_tree(struct fs_context *fc) { - return get_tree_single(fc, securityfs_fill_super); + return get_tree_keyed(fc, securityfs_fill_super, fc->user_ns); } static const struct fs_context_operations securityfs_context_ops = { @@ -72,6 +72,7 @@ static struct file_system_type fs_type = { .name = "securityfs", .init_fs_context = securityfs_init_fs_context, .kill_sb = kill_litter_super, + .fs_flags = FS_USERNS_MOUNT, }; /** @@ -168,7 +169,6 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, inode->i_fop = fops; } d_instantiate(dentry, inode); - dget(dentry); inode_unlock(dir); return dentry; @@ -306,23 +306,17 @@ EXPORT_SYMBOL_GPL(securityfs_create_symlink); void securityfs_remove(struct dentry *dentry) { struct user_namespace *ns; - struct inode *dir; if (!dentry || IS_ERR(dentry)) return; ns = dentry->d_sb->s_user_ns; - dir = d_inode(dentry->d_parent); - inode_lock(dir); if (simple_positive(dentry)) { - if (d_is_dir(dentry)) - simple_rmdir(dir, dentry); - else - simple_unlink(dir, dentry); + d_delete(dentry); dput(dentry); } - inode_unlock(dir); + if (ns == &init_user_ns) simple_release_fs(&init_securityfs_mount, &init_securityfs_mount_count); From patchwork Fri Dec 10 19:47:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670821 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 452DAC43217 for ; Fri, 10 Dec 2021 19:47:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242527AbhLJTvc (ORCPT ); Fri, 10 Dec 2021 14:51:32 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:7772 "EHLO mx0b-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343706AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAHoFel015809; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=CRhNOUjlLEyyqfUxlHtoE0Pvo8ekfwaBk7aKkhXadp0=; b=N2s8dM2Gdo0LxMFjkTKmkelOz9HLrMH3juL3LTs/53yH84kegLTwYTjmiP3L0cn77XjX LMcJQFSIb/r6THofQUxRAF7alsQWsjDxtuwu4GsCu+M6EzwgS0rMzSdnvxkjAhJ4dmvG EBqQKgLB1+19nt3nX4aGohvu1SzULb7ZQHoD+OfKK6PYbkg8ke+S/VkRhPHFh/tJxOTX c5tfEWPBJ3yBk5SWg9zYEOu8Av6PYknqB9OLpPjVc176fovX5RPDogFRB0F2IoP/tjWm PlcMGPkHxQESIzmkvSZCvPIMuk0wnzvLYuslt+6LuGSvGdpnGh7YdwJCTC0gPpiHBU32 Xw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubgv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098421.ppops.net (m0098421.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAIs6ED030965; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma02wdc.us.ibm.com (aa.5b.37a9.ip4.static.sl-reverse.com [169.55.91.170]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvavkubgg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma02wdc.us.ibm.com [127.0.0.1]) by ppma02wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcKPd016571; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma02wdc.us.ibm.com with ESMTP id 3cqyycnqgs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldUj26214886 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8B605AE068; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7871CAE06B; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 13/17] ima: Move some IMA policy and filesystem related variables into ima_namespace Date: Fri, 10 Dec 2021 14:47:32 -0500 Message-Id: <20211210194736.1538863-14-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: DUw-jddaBrHCd8gYHVNQCGiLhp1JTUG_ X-Proofpoint-GUID: TEU_qlJ3BLjaIp_IYpAK0tJOO7vGITN7 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 phishscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 spamscore=0 mlxlogscore=999 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move the ima_write_mutex, ima_fs_flag, and valid_policy variables into ima_namespace. This way each IMA namespace can set those variables independently. Signed-off-by: Stefan Berger --- include/linux/ima.h | 5 ++++ security/integrity/ima/ima_fs.c | 32 +++++++++++------------- security/integrity/ima/ima_init_ima_ns.c | 4 +++ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index fda371cbde50..ca300306a715 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -268,6 +268,11 @@ struct ima_namespace { struct ima_h_table ima_htable; struct list_head ima_measurements; unsigned long binary_runtime_size; + + /* IMA's filesystem */ + struct mutex ima_write_mutex; + unsigned long ima_fs_flags; + int valid_policy; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 38b1c26479b3..0e582ceecc7f 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -25,8 +25,6 @@ #include "ima.h" -static DEFINE_MUTEX(ima_write_mutex); - bool ima_canonical_fmt; static int __init default_canonical_fmt_setup(char *str) { @@ -37,8 +35,6 @@ static int __init default_canonical_fmt_setup(char *str) } __setup("ima_canonical_fmt", default_canonical_fmt_setup); -static int valid_policy = 1; - static ssize_t ima_show_htable_value(char __user *buf, size_t count, loff_t *ppos, atomic_long_t *val) { @@ -339,7 +335,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, goto out; } - result = mutex_lock_interruptible(&ima_write_mutex); + result = mutex_lock_interruptible(&ns->ima_write_mutex); if (result < 0) goto out_free; @@ -354,12 +350,12 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, } else { result = ima_parse_add_rule(ns, data); } - mutex_unlock(&ima_write_mutex); + mutex_unlock(&ns->ima_write_mutex); out_free: kfree(data); out: if (result < 0) - valid_policy = 0; + ns->valid_policy = 0; return result; } @@ -376,8 +372,6 @@ enum ima_fs_flags { IMA_FS_BUSY, }; -static unsigned long ima_fs_flags; - #ifdef CONFIG_IMA_READ_POLICY static const struct seq_operations ima_policy_seqops = { .start = ima_policy_start, @@ -392,6 +386,8 @@ static const struct seq_operations ima_policy_seqops = { */ static int ima_open_policy(struct inode *inode, struct file *filp) { + struct ima_namespace *ns = get_current_ns(); + if (!(filp->f_flags & O_WRONLY)) { #ifndef CONFIG_IMA_READ_POLICY return -EACCES; @@ -403,7 +399,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) return seq_open(filp, &ima_policy_seqops); #endif } - if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags)) + if (test_and_set_bit(IMA_FS_BUSY, &ns->ima_fs_flags)) return -EBUSY; return 0; } @@ -417,25 +413,25 @@ static int ima_open_policy(struct inode *inode, struct file *filp) */ static int ima_release_policy(struct inode *inode, struct file *file) { - const char *cause = valid_policy ? "completed" : "failed"; struct ima_namespace *ns = get_current_ns(); + const char *cause = ns->valid_policy ? "completed" : "failed"; if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); - if (valid_policy && ima_check_policy(ns) < 0) { + if (ns->valid_policy && ima_check_policy(ns) < 0) { cause = "failed"; - valid_policy = 0; + ns->valid_policy = 0; } pr_info("policy update %s\n", cause); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, - "policy_update", cause, !valid_policy, 0); + "policy_update", cause, !ns->valid_policy, 0); - if (!valid_policy) { + if (!ns->valid_policy) { ima_delete_rules(ns); - valid_policy = 1; - clear_bit(IMA_FS_BUSY, &ima_fs_flags); + ns->valid_policy = 1; + clear_bit(IMA_FS_BUSY, &ns->ima_fs_flags); return 0; } @@ -444,7 +440,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) securityfs_remove(ima_policy); ima_policy = NULL; #elif defined(CONFIG_IMA_WRITE_POLICY) - clear_bit(IMA_FS_BUSY, &ima_fs_flags); + clear_bit(IMA_FS_BUSY, &ns->ima_fs_flags); #elif defined(CONFIG_IMA_READ_POLICY) inode->i_mode &= ~S_IWUSR; #endif diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index 3bec9a2a0bd9..02cefc657c88 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -49,6 +49,10 @@ int ima_init_namespace(struct ima_namespace *ns) else ns->binary_runtime_size = ULONG_MAX; + mutex_init(&ns->ima_write_mutex); + ns->valid_policy = 1; + ns->ima_fs_flags = 0; + return 0; } From patchwork Fri Dec 10 19:47:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670823 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C8A0C433F5 for ; Fri, 10 Dec 2021 19:48:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343549AbhLJTvf (ORCPT ); Fri, 10 Dec 2021 14:51:35 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:25496 "EHLO mx0b-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343711AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0127361.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAIv3DV017087; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=4tGjfzkjMGQ2KgjPK3Ll+QStpNIq21ZlivCJTVWdi3M=; b=KaEMI0m1mwAz4/jfHQab4px83k3i4MrqteWtp7VzfOD7fLVBOQOi4n+w6aN77YIuTTcC TdvYO0t74UtkZUUwHekqcp3rFUK0wcUfrfPjv5ab72hYnBMQcx6wyF21+K1rZIhPKg0W mKKdnegG8xBs6/ndYjZSEKUSfPx+sEoG3E5GFIMwdE7KV/z5GiihTGjkovopuv4C3uKW ml8oHpeggDpfjiunIegLXKDjwd5FzxGxLbgcn1rCQ5SF30Em/MxJToo/YeZAofPO62Zj 8MW2OwLTVbvm39KRGyRTrcOKHiQ5jxuW0KEDkGDGc5xoNngVQxa1TEzL82SwXwT6jU8I Fg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvcmes0sn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from m0127361.ppops.net (m0127361.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJecd2001605; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma04wdc.us.ibm.com (1a.90.2fa9.ip4.static.sl-reverse.com [169.47.144.26]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cvcmes0sc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma04wdc.us.ibm.com [127.0.0.1]) by ppma04wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcDSu028115; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma04wdc.us.ibm.com with ESMTP id 3cqyycns5v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldwq26214888 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B38D1AE06A; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 95BC6AE064; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 14/17] ima: Tie opened SecurityFS files to the IMA namespace it belongs to Date: Fri, 10 Dec 2021 14:47:33 -0500 Message-Id: <20211210194736.1538863-15-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: ezDsSUc3jztVFRcGJyhBUeoeeLtevKQa X-Proofpoint-GUID: YBBYPq93c9aDIbGvG8mESVRbwn52nRyR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 adultscore=0 bulkscore=0 suspectscore=0 lowpriorityscore=0 mlxscore=0 priorityscore=1501 phishscore=0 malwarescore=0 impostorscore=0 clxscore=1015 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Tie IMA's files in SecurityFS to the IMA namespace they belong to so that also file descriptor that were passed or inherited to other user/IMA namespaces will always access the data of the IMA namespace they originally belonged to. Signed-off-by: Stefan Berger --- security/integrity/ima/ima_fs.c | 74 ++++++++++++++++++++++++----- security/integrity/ima/ima_policy.c | 4 +- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 0e582ceecc7f..a136d14f29ec 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -35,6 +35,20 @@ static int __init default_canonical_fmt_setup(char *str) } __setup("ima_canonical_fmt", default_canonical_fmt_setup); +static inline struct user_namespace *ima_user_ns_from_file(struct file *filp) +{ + return filp->f_path.mnt->mnt_sb->s_user_ns; +} + +static int ima_open(struct inode *inode, struct file *file) +{ + struct user_namespace *user_ns = ima_user_ns_from_file(file); + struct ima_namespace *ns = user_ns->ima_ns; + + file->private_data = ns; + return 0; +} + static ssize_t ima_show_htable_value(char __user *buf, size_t count, loff_t *ppos, atomic_long_t *val) { @@ -49,12 +63,13 @@ static ssize_t ima_show_htable_violations(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = filp->private_data; return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.violations); } static const struct file_operations ima_htable_violations_ops = { + .open = ima_open, .read = ima_show_htable_violations, .llseek = generic_file_llseek, }; @@ -63,12 +78,13 @@ static ssize_t ima_show_measurements_count(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = filp->private_data; return ima_show_htable_value(buf, count, ppos, &ns->ima_htable.len); } static const struct file_operations ima_measurements_count_ops = { + .open = ima_open, .read = ima_show_measurements_count, .llseek = generic_file_llseek, }; @@ -76,7 +92,7 @@ static const struct file_operations ima_measurements_count_ops = { /* returns pointer to hlist_node */ static void *ima_measurements_start(struct seq_file *m, loff_t *pos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = m->private; loff_t l = *pos; struct ima_queue_entry *qe; @@ -94,7 +110,7 @@ static void *ima_measurements_start(struct seq_file *m, loff_t *pos) static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = m->private; struct ima_queue_entry *qe = v; /* lock protects when reading beyond last element @@ -195,9 +211,26 @@ static const struct seq_operations ima_measurments_seqops = { .show = ima_measurements_show }; +static int ima_seq_open(struct file *file, const struct seq_operations *seq_ops) +{ + struct user_namespace *user_ns = ima_user_ns_from_file(file); + struct ima_namespace *ns = user_ns->ima_ns; + struct seq_file *seq; + int err; + + err = seq_open(file, seq_ops); + if (err) + return err; + + seq = file->private_data; + seq->private = ns; + + return 0; +} + static int ima_measurements_open(struct inode *inode, struct file *file) { - return seq_open(file, &ima_measurments_seqops); + return ima_seq_open(file, &ima_measurments_seqops); } static const struct file_operations ima_measurements_ops = { @@ -263,7 +296,7 @@ static const struct seq_operations ima_ascii_measurements_seqops = { static int ima_ascii_measurements_open(struct inode *inode, struct file *file) { - return seq_open(file, &ima_ascii_measurements_seqops); + return ima_seq_open(file, &ima_ascii_measurements_seqops); } static const struct file_operations ima_ascii_measurements_ops = { @@ -273,9 +306,8 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, }; -static ssize_t ima_read_policy(char *path) +static ssize_t ima_read_policy(struct ima_namespace *ns, char *path) { - struct ima_namespace *ns = get_current_ns(); void *data = NULL; char *datap; size_t size; @@ -314,10 +346,23 @@ static ssize_t ima_read_policy(char *path) return pathlen; } +static struct ima_namespace *ima_filp_private(struct file *filp) +{ + if (!(filp->f_flags & O_WRONLY)) { +#ifdef CONFIG_IMA_READ_POLICY + struct seq_file *seq; + + seq = filp->private_data; + return seq->private; +#endif + } + return filp->private_data; +} + static ssize_t ima_write_policy(struct file *file, const char __user *buf, size_t datalen, loff_t *ppos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = ima_filp_private(file); char *data; ssize_t result; @@ -340,7 +385,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, goto out_free; if (data[0] == '/') { - result = ima_read_policy(data); + result = ima_read_policy(ns, data); } else if (ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified as an absolute pathname) required\n"); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, @@ -386,7 +431,8 @@ static const struct seq_operations ima_policy_seqops = { */ static int ima_open_policy(struct inode *inode, struct file *filp) { - struct ima_namespace *ns = get_current_ns(); + struct user_namespace *user_ns = ima_user_ns_from_file(filp); + struct ima_namespace *ns = user_ns->ima_ns; if (!(filp->f_flags & O_WRONLY)) { #ifndef CONFIG_IMA_READ_POLICY @@ -396,11 +442,13 @@ static int ima_open_policy(struct inode *inode, struct file *filp) return -EACCES; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - return seq_open(filp, &ima_policy_seqops); + return ima_seq_open(filp, &ima_policy_seqops); #endif } if (test_and_set_bit(IMA_FS_BUSY, &ns->ima_fs_flags)) return -EBUSY; + + filp->private_data = ns; return 0; } @@ -413,7 +461,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) */ static int ima_release_policy(struct inode *inode, struct file *file) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = ima_filp_private(file); const char *cause = ns->valid_policy ? "completed" : "failed"; if ((file->f_flags & O_ACCMODE) == O_RDONLY) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 747dca6131d6..c2acd4cf529d 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1908,7 +1908,7 @@ static const char *const mask_tokens[] = { void *ima_policy_start(struct seq_file *m, loff_t *pos) { - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = m->private; loff_t l = *pos; struct ima_rule_entry *entry; struct list_head *ima_rules_tmp; @@ -1928,7 +1928,7 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) { struct ima_rule_entry *entry = v; - struct ima_namespace *ns = get_current_ns(); + struct ima_namespace *ns = m->private; rcu_read_lock(); entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list); From patchwork Fri Dec 10 19:47:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670827 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 38E6AC4332F for ; Fri, 10 Dec 2021 19:48:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343744AbhLJTvg (ORCPT ); Fri, 10 Dec 2021 14:51:36 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:59404 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343714AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJRlTY004895; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=DAqSnX3gkM3wc0FEX16t1Vzz0Kiqgw4SET/J5zHYMCE=; b=WSwGo9AZJaW+dOZNhWK2n81lGCoUZONzeQO/X/HYE7ojxL4Y27UlkJDMDDTxaLb+XyS7 kADaQ/8YJeAYeI9tZViHxK6/gEqiN77h067X0nijhYN641zFKtMsCs/5KFRe5WzPcubY qIqKjpNu8LKfymVwdy49Q0EvIKnXVfgp8zZH6U+SdFTfnnMKcE+FbqoDzn1Vt8SNEKUZ wtdeVh3DtjYSzVa3pLTh+1We219FZ8vin4W+CQVN51U6d9HZrL94xEUT4uRZY0+t7JO8 GYCwf77zOV6DbUPGLsIQj6AHDrJzLjUckGRFGgoI7I1J3dZjWGK/QcUYHI/r+IY6UTzx oA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2v0a0s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJVhDW020934; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma04dal.us.ibm.com (7a.29.35a9.ip4.static.sl-reverse.com [169.53.41.122]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2v0a0c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma04dal.us.ibm.com [127.0.0.1]) by ppma04dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcNY7001943; Fri, 10 Dec 2021 19:47:41 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma04dal.us.ibm.com with ESMTP id 3cqyydbsqe-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJldBb29753830 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:39 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C6036AE067; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B43C8AE06B; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , Denis Semakin Subject: [PATCH v6 15/17] ima: Use mac_admin_ns_capable() to check corresponding capability Date: Fri, 10 Dec 2021 14:47:34 -0500 Message-Id: <20211210194736.1538863-16-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: pCoBJ9HMt-DObsVwXgHNBWBLBUvA7zDG X-Proofpoint-ORIG-GUID: bOeJt4n3-6IOyIzaj7T2g-rATAxMwt0M X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 clxscore=1015 mlxscore=0 phishscore=0 impostorscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Use mac_admin_ns_capable() to check corresponding capability to allow read/write IMA policy without CAP_SYS_ADMIN but with CAP_MAC_ADMIN. Signed-off-by: Denis Semakin Signed-off-by: Stefan Berger --- include/linux/capability.h | 6 ++++++ security/integrity/ima/ima_fs.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 65efb74c3585..991579178f32 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -270,6 +270,12 @@ static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns) ns_capable(ns, CAP_SYS_ADMIN); } +static inline bool mac_admin_ns_capable(struct user_namespace *ns) +{ + return ns_capable(ns, CAP_MAC_ADMIN) || + ns_capable(ns, CAP_SYS_ADMIN); +} + /* audit system wants to get cap info from files as well */ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, const struct dentry *dentry, diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index a136d14f29ec..090ee85bfa3a 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -440,7 +440,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) #else if ((filp->f_flags & O_ACCMODE) != O_RDONLY) return -EACCES; - if (!capable(CAP_SYS_ADMIN)) + if (!mac_admin_ns_capable(user_ns)) return -EPERM; return ima_seq_open(filp, &ima_policy_seqops); #endif From patchwork Fri Dec 10 19:47:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670829 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D4CEC433FE for ; Fri, 10 Dec 2021 19:48:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242404AbhLJTvj (ORCPT ); Fri, 10 Dec 2021 14:51:39 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:20286 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343723AbhLJTva (ORCPT ); Fri, 10 Dec 2021 14:51:30 -0500 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJT7qd007275; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=u6PgdV+NKwF7N9A69Elc9vH38PnC24ZEh2+pcZ+phZg=; b=XER5yorF6KXEDUfRLW6Lfvw9On266NJ/MXoxaj/37ESub3vTioFJcZ41/aQsz9mH33K9 B/KuNgMW0GAt/8AE22cK/uVojBXK2FRO/prZkrbhx8HgidbaYGjMJ8CjKOvEF8M/82Tu FtIiRUOzra46jB8Rl1kZ6OkJHHYf1kWbzFtezSLpvzOeueV14tFeWuZ0uvYHBSalahKl +fAMNnm9HcUNC9sC3clVvaHHISn23eEcdmbwuKk7y0sHkd4XExZrB8nfMP0YvC++gVyA rplGasBnNPghqK1x8K3UWMrhN9V1YMHqCstk9jBtGjqwta9z6RWLj0kv2oKdk0/P5J4V Nw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd370a17-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098413.ppops.net (m0098413.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJgB41029194; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma02dal.us.ibm.com (a.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.10]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd370a0w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma02dal.us.ibm.com [127.0.0.1]) by ppma02dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJlHLd029464; Fri, 10 Dec 2021 19:47:41 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma02dal.us.ibm.com with ESMTP id 3cqyydm09u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJleL012976630 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:40 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E3FA2AE060; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C706FAE064; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger Subject: [PATCH v6 16/17] ima: Move dentry into ima_namespace and others onto stack Date: Fri, 10 Dec 2021 14:47:35 -0500 Message-Id: <20211210194736.1538863-17-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: pualFYN857t0R6rlgU8boLoVTR670g6C X-Proofpoint-GUID: 2SRy88NSXkwGdBZCikDEj2S3f9mbeIzs X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 clxscore=1015 mlxscore=0 malwarescore=0 spamscore=0 bulkscore=0 impostorscore=0 mlxlogscore=999 phishscore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Move the policy file dentry into the ima_namespace for reuse by virtualized SecurityFS and for being able to remove it from the filesystem. Move the other dentries onto the stack. Signed-off-by: Stefan Berger --- include/linux/ima.h | 2 ++ security/integrity/ima/ima_fs.c | 33 +++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index ca300306a715..cc950ccbf157 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -273,6 +273,8 @@ struct ima_namespace { struct mutex ima_write_mutex; unsigned long ima_fs_flags; int valid_policy; + + struct dentry *policy_dentry; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 090ee85bfa3a..84b3bf2f1454 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -405,14 +405,6 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, return result; } -static struct dentry *ima_dir; -static struct dentry *ima_symlink; -static struct dentry *binary_runtime_measurements; -static struct dentry *ascii_runtime_measurements; -static struct dentry *runtime_measurements_count; -static struct dentry *violations; -static struct dentry *ima_policy; - enum ima_fs_flags { IMA_FS_BUSY, }; @@ -485,8 +477,8 @@ static int ima_release_policy(struct inode *inode, struct file *file) ima_update_policy(ns); #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY) - securityfs_remove(ima_policy); - ima_policy = NULL; + securityfs_remove(ns->policy_dentry); + ns->policy_dentry = NULL; #elif defined(CONFIG_IMA_WRITE_POLICY) clear_bit(IMA_FS_BUSY, &ns->ima_fs_flags); #elif defined(CONFIG_IMA_READ_POLICY) @@ -503,8 +495,16 @@ static const struct file_operations ima_measure_policy_ops = { .llseek = generic_file_llseek, }; -int __init ima_fs_init(void) +static int __init ima_fs_ns_init(struct user_namespace *user_ns) { + struct ima_namespace *ns = user_ns->ima_ns; + struct dentry *ima_dir; + struct dentry *ima_symlink = NULL; + struct dentry *binary_runtime_measurements = NULL; + struct dentry *ascii_runtime_measurements = NULL; + struct dentry *runtime_measurements_count = NULL; + struct dentry *violations = NULL; + ima_dir = securityfs_create_dir("ima", integrity_dir); if (IS_ERR(ima_dir)) return -1; @@ -541,20 +541,25 @@ int __init ima_fs_init(void) if (IS_ERR(violations)) goto out; - ima_policy = securityfs_create_file("policy", POLICY_FILE_FLAGS, + ns->policy_dentry = securityfs_create_file("policy", POLICY_FILE_FLAGS, ima_dir, NULL, &ima_measure_policy_ops); - if (IS_ERR(ima_policy)) + if (IS_ERR(ns->policy_dentry)) goto out; return 0; out: + securityfs_remove(ns->policy_dentry); securityfs_remove(violations); securityfs_remove(runtime_measurements_count); securityfs_remove(ascii_runtime_measurements); securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_symlink); securityfs_remove(ima_dir); - securityfs_remove(ima_policy); return -1; } + +int __init ima_fs_init(void) +{ + return ima_fs_ns_init(&init_user_ns); +} From patchwork Fri Dec 10 19:47:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670817 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64D50C43219 for ; Fri, 10 Dec 2021 19:47:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238273AbhLJTva (ORCPT ); Fri, 10 Dec 2021 14:51:30 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:9506 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343707AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJRlLq004890; Fri, 10 Dec 2021 19:47:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=eYWEmDlzCVAiGJLTBHVFTM/ZODKRMSFQ2u0Jgxs2IC8=; b=YlQ/y114xDeLOAeVWMBXGOoRsDYa9OaXAYGbt3ZbAdkd7QTY+D/XGDnrAlrVEZPQoOpB 2cH06eZLTjjE3nltPpZz4Cf+dZBlVvazVOjyOLZ9v0p9iesTOHdyxCYIMK7JH1XCu8Me 2LVrI02N4+tsw3NiABzLCBdpi+sEszd2kvpOCMUZ0mznPmRVP+T7vU4E7nn2yHBpAFvk T696BbClkCb4ggFri+7XS+O1tNzBsE3J88v4avVO3pDTMYNsU+8Wv2cYr+NAJ25q3yOG Ak6X/UOSDNxm61e8hYaWg2UKqL2mQ0VjNodBm0zyidHv/ZuKlH0u3pQCiwvU30BvhQM2 lA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2v0a0p-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:42 +0000 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJSZhV007661; Fri, 10 Dec 2021 19:47:41 GMT Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2v0a0b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:41 +0000 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJcgUO013152; Fri, 10 Dec 2021 19:47:40 GMT Received: from b01cxnp22036.gho.pok.ibm.com (b01cxnp22036.gho.pok.ibm.com [9.57.198.26]) by ppma01wdc.us.ibm.com with ESMTP id 3cqyycnqk5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22036.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlexq8061584 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:40 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0D9F1AE05F; Fri, 10 Dec 2021 19:47:40 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E54C2AE067; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:39 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , James Bottomley Subject: [PATCH v6 17/17] ima: Setup securityfs for IMA namespace Date: Fri, 10 Dec 2021 14:47:36 -0500 Message-Id: <20211210194736.1538863-18-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: Hwo6Bjyz6GGOr1tOsRo4RoBd8GBnN3qq X-Proofpoint-ORIG-GUID: DoieSRaiN9daNSgfDvGlM80uH4zFymWY X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 clxscore=1015 mlxscore=0 phishscore=0 impostorscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 priorityscore=1501 adultscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Setup securityfs with symlinks, directories, and files for IMA namespacing support. The same directory structure that IMA uses on the host is also created for the namespacing case. The securityfs file and directory ownerships cannot be set when the IMA namespace is initialized. Therefore, delay the setup of the file system to a later point when securityfs is in securityfs_fill_super. This filesystem can now be mounted as follows: mount -t securityfs /sys/kernel/security/ /sys/kernel/security/ The following directories, symlinks, and files are then available. $ ls -l sys/kernel/security/ total 0 lr--r--r--. 1 root root 0 Dec 2 00:18 ima -> integrity/ima drwxr-xr-x. 3 root root 0 Dec 2 00:18 integrity $ ls -l sys/kernel/security/ima/ total 0 -r--r-----. 1 root root 0 Dec 2 00:18 ascii_runtime_measurements -r--r-----. 1 root root 0 Dec 2 00:18 binary_runtime_measurements -rw-------. 1 root root 0 Dec 2 00:18 policy -r--r-----. 1 root root 0 Dec 2 00:18 runtime_measurements_count -r--r-----. 1 root root 0 Dec 2 00:18 violations Signed-off-by: Stefan Berger Signed-off-by: James Bottomley --- include/linux/ima.h | 15 ++++++++++++- security/inode.c | 7 +++++- security/integrity/ima/ima_fs.c | 40 ++++++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index cc950ccbf157..5524f439d9cf 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -40,6 +40,7 @@ extern int ima_measure_critical_data(const char *event_label, const char *event_name, const void *buf, size_t buf_len, bool hash, u8 *digest, size_t digest_len); +extern int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root); #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM extern void ima_appraise_parse_cmdline(void); @@ -275,6 +276,7 @@ struct ima_namespace { int valid_policy; struct dentry *policy_dentry; + bool policy_dentry_removed; }; extern struct ima_namespace init_ima_ns; @@ -284,12 +286,17 @@ extern struct list_head ima_default_rules; void free_ima_ns(struct user_namespace *ns); int create_ima_ns(struct user_namespace *user_ns); - static inline struct ima_namespace *get_current_ns(void) { return current_user_ns()->ima_ns; } +static inline int ima_securityfs_init(struct user_namespace *user_ns, + struct dentry *root) +{ + return ima_fs_ns_init(user_ns, root); +} + #else static inline void free_ima_ns(struct user_namespace *user_ns) @@ -308,6 +315,12 @@ static inline struct ima_namespace *get_current_ns(void) { return &init_ima_ns; } + +static inline int ima_securityfs_init(struct user_namespace *ns, struct dentry *root) +{ + return 0; +} + #endif /* CONFIG_IMA_NS */ #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) diff --git a/security/inode.c b/security/inode.c index c77ae8ecc464..c9327389ad80 100644 --- a/security/inode.c +++ b/security/inode.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ static const struct super_operations securityfs_super_operations = { static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc) { static const struct tree_descr files[] = {{""}}; + struct user_namespace *ns = fc->user_ns; int error; error = simple_fill_super(sb, SECURITYFS_MAGIC, files); @@ -49,7 +51,10 @@ static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_op = &securityfs_super_operations; - return 0; + if (ns != &init_user_ns) + error = ima_securityfs_init(ns, sb->s_root); + + return error; } static int securityfs_get_tree(struct fs_context *fc) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 84b3bf2f1454..f1c3cde25c80 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -479,6 +479,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) #if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY) securityfs_remove(ns->policy_dentry); ns->policy_dentry = NULL; + ns->policy_dentry_removed = true; #elif defined(CONFIG_IMA_WRITE_POLICY) clear_bit(IMA_FS_BUSY, &ns->ima_fs_flags); #elif defined(CONFIG_IMA_READ_POLICY) @@ -495,21 +496,31 @@ static const struct file_operations ima_measure_policy_ops = { .llseek = generic_file_llseek, }; -static int __init ima_fs_ns_init(struct user_namespace *user_ns) +int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root) { struct ima_namespace *ns = user_ns->ima_ns; - struct dentry *ima_dir; + struct dentry *int_dir; + struct dentry *ima_dir = NULL; struct dentry *ima_symlink = NULL; struct dentry *binary_runtime_measurements = NULL; struct dentry *ascii_runtime_measurements = NULL; struct dentry *runtime_measurements_count = NULL; struct dentry *violations = NULL; - ima_dir = securityfs_create_dir("ima", integrity_dir); + /* FIXME: update when evm and integrity are namespaced */ + if (user_ns != &init_user_ns) { + int_dir = + securityfs_create_dir("integrity", root); + if (IS_ERR(int_dir)) + return -1; + } else + int_dir = integrity_dir; + + ima_dir = securityfs_create_dir("ima", int_dir); if (IS_ERR(ima_dir)) - return -1; + goto out; - ima_symlink = securityfs_create_symlink("ima", NULL, "integrity/ima", + ima_symlink = securityfs_create_symlink("ima", root, "integrity/ima", NULL); if (IS_ERR(ima_symlink)) goto out; @@ -541,11 +552,15 @@ static int __init ima_fs_ns_init(struct user_namespace *user_ns) if (IS_ERR(violations)) goto out; - ns->policy_dentry = securityfs_create_file("policy", POLICY_FILE_FLAGS, - ima_dir, NULL, - &ima_measure_policy_ops); - if (IS_ERR(ns->policy_dentry)) - goto out; + + if (!ns->policy_dentry_removed) { + ns->policy_dentry = + securityfs_create_file("policy", POLICY_FILE_FLAGS, + ima_dir, NULL, + &ima_measure_policy_ops); + if (IS_ERR(ns->policy_dentry)) + goto out; + } return 0; out: @@ -556,10 +571,13 @@ static int __init ima_fs_ns_init(struct user_namespace *user_ns) securityfs_remove(binary_runtime_measurements); securityfs_remove(ima_symlink); securityfs_remove(ima_dir); + if (user_ns != &init_user_ns) + securityfs_remove(integrity_dir); + return -1; } int __init ima_fs_init(void) { - return ima_fs_ns_init(&init_user_ns); + return ima_fs_ns_init(&init_user_ns, NULL); }