From patchwork Tue Nov 30 16:06: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: 12647665 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 6A1F7C433FE for ; Tue, 30 Nov 2021 16:07:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238109AbhK3QKr (ORCPT ); Tue, 30 Nov 2021 11:10:47 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:38810 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S238082AbhK3QKr (ORCPT ); Tue, 30 Nov 2021 11:10:47 -0500 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFlGAI009536; Tue, 30 Nov 2021 16:07:14 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=jRs6taGYxPxVo4hRoaynr8Ids0+FxGioya6MVwDlk8I=; b=DX3lf+aT+RIolJJbLeICGyYk+uOYKSTzghigGiLzy3/urRT2MF2aoWoe6jxmU/DpsB+j yrq57vwyUveCjpuHJf7bIyqCUlh+UY3KlDtmGGTWhGkNNGuLuHb4hHotFvqxcP3EFRzB QIANWWx5uy3z3hVJNCbuopCGzcChKn7dH5mpYQIzJVlOA5NCwgSRoz+0UQsXYWv/56tI zVT67n7n3v7lc3yMAs/YtMVqIkAJnYUrwVlRIrV3LzO3pdYQlCPDKAhH35EgAbjbG1vQ 5bCX45LJ82JSHBn+93hnMmluVBQDB1Gw0KHOB/OgtGGNMk9qhlSnl06mQfCebGaRGzlS 0w== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cnpwggfdx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:13 +0000 Received: from m0098420.ppops.net (m0098420.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFq20D026555; Tue, 30 Nov 2021 16:07:13 GMT Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cnpwggfdm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:13 +0000 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1AUG4Buk003709; Tue, 30 Nov 2021 16:07:12 GMT Received: from b01cxnp23032.gho.pok.ibm.com (b01cxnp23032.gho.pok.ibm.com [9.57.198.27]) by ppma05wdc.us.ibm.com with ESMTP id 3ckcaayt8g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:12 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23032.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7ADT42271078 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:10 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B77E8B2072; Tue, 30 Nov 2021 16:07:10 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9121BB2071; Tue, 30 Nov 2021 16:07:10 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:10 +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: [RFC 01/20] ima: Add IMA namespace support Date: Tue, 30 Nov 2021 11:06:35 -0500 Message-Id: <20211130160654.1418231-2-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: kPOjLpj18wlZl8ZFkKp4OO_Kaa3vwUui X-Proofpoint-GUID: Qs449YghkTKhWGruBbb4TB1V6Ya7kNDb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 malwarescore=0 phishscore=0 bulkscore=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 spamscore=0 clxscore=1011 suspectscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 59 +++++++++++++++++ include/linux/user_namespace.h | 4 ++ init/Kconfig | 9 +++ kernel/user.c | 9 ++- kernel/user_namespace.c | 16 +++++ 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 | 82 ++++++++++++++++++++++++ 10 files changed, 220 insertions(+), 2 deletions(-) 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..86d126b9ff2f 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,64 @@ static inline int ima_inode_removexattr(struct dentry *dentry, } #endif /* CONFIG_IMA_APPRAISE */ +struct ima_namespace { + struct kref kref; + struct user_namespace *user_ns; +}; + +extern struct ima_namespace init_ima_ns; + +#ifdef CONFIG_IMA_NS + +void free_ima_ns(struct kref *kref); + +static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns) +{ + if (ns) + kref_get(&ns->kref); + + return ns; +} + +static inline void put_ima_ns(struct ima_namespace *ns) +{ + if (ns) { + pr_debug("DEREF ima_ns: 0x%p ctr: %d\n", ns, kref_read(&ns->kref)); + kref_put(&ns->kref, free_ima_ns); + } +} + +struct ima_namespace *copy_ima_ns(struct ima_namespace *old_ns, + struct user_namespace *user_ns); + +static inline struct ima_namespace *get_current_ns(void) +{ + return current_user_ns()->ima_ns; +} + +#else + +static inline struct ima_namespace *get_ima_ns(struct ima_namespace *ns) +{ + return ns; +} + +static inline void put_ima_ns(struct ima_namespace *ns) +{ +} + +static inline struct ima_namespace *copy_ima_ns(struct ima_namespace *old_ns, + struct user_namespace *user_ns) +{ + return old_ns; +} + +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..598baf451a54 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1242,6 +1242,15 @@ 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 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..b5dc803a033d 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... ? @@ -55,7 +59,7 @@ struct user_namespace init_user_ns = { }, }, }, - .ns.count = REFCOUNT_INIT(3), + .ns.count = REFCOUNT_INIT(4), .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, .ns.inum = PROC_USER_INIT_INO, @@ -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..c26885343b19 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,20 @@ int create_user_ns(struct cred *new) if (!setup_userns_sysctls(ns)) goto fail_keyring; +#if CONFIG_IMA + ns->ima_ns = copy_ima_ns(parent_ns->ima_ns, ns); + if (IS_ERR(ns->ima_ns)) { + ret = PTR_ERR(ns->ima_ns); + goto fail_userns_sysctls; + } +#endif + set_cred_user_ns(new, ns); return 0; +#if CONFIG_IMA +fail_userns_sysctls: + retire_userns_sysctls(ns); +#endif fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); @@ -196,6 +209,9 @@ static void free_user_ns(struct work_struct *work) kfree(ns->projid_map.forward); kfree(ns->projid_map.reverse); } +#ifdef CONFIG_IMA + put_ima_ns(ns->ima_ns); +#endif 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..12723d77fe17 --- /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-2018 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 + +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 = { + .kref = KREF_INIT(1), + .user_ns = &init_user_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..fa8069acc217 --- /dev/null +++ b/security/integrity/ima/ima_ns.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2018 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; + +static struct ima_namespace *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 ERR_PTR(-ENOMEM); + pr_debug("NEW ima_ns: 0x%p\n", ns); + + kref_init(&ns->kref); + ns->user_ns = user_ns; + + err = ima_init_namespace(ns); + if (err) + goto fail_free; + + return ns; + +fail_free: + kmem_cache_free(imans_cachep, ns); + + return ERR_PTR(err); +} + +/** + * Copy an ima namespace - create a new one + * + * @old_ns: old ima namespace to clone + * @user_ns: User namespace + */ +struct ima_namespace *copy_ima_ns(struct ima_namespace *old_ns, + struct user_namespace *user_ns) +{ + return create_ima_ns(user_ns); +} + +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 kref *kref) +{ + struct ima_namespace *ns; + + ns = container_of(kref, struct ima_namespace, kref); + BUG_ON(ns == &init_ima_ns); + + destroy_ima_ns(ns); +} + +int __init imans_cache_init(void) +{ + imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); + return 0; +} +subsys_initcall(imans_cache_init) From patchwork Tue Nov 30 16:06: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: 12647679 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 BEB89C4332F for ; Tue, 30 Nov 2021 16:07:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243594AbhK3QLQ (ORCPT ); Tue, 30 Nov 2021 11:11:16 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:39512 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232957AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -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 1AUFQDex010488; Tue, 30 Nov 2021 16:07:15 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=ZhtMD1/gN5AauMyy4F6FSlYYhZ3zZKJ2CjN5QGYzZPk=; b=Wj7V9jkxYqdjqagQQfrJYrQFpz8obNxQ1FY4qb7thnb1QZpNAWtS5oeswJJUPSf75XrA uKRfk5SqcVtIsOfoseOWosY22/Tq5SFSJh5gWp4YEmg8RAUHRV2XWy2eHTotR2ULPsO9 y4ddK6rcUVivLLruAmTSsE/WzfmtXEiKgPJyftACojShmhaSZMNY+r1zjHrEqrk32Wy+ I4DVym+OsDbGLVOvudEuXxs6sAPb0RD8ikZs52B15jI33o8Gri4B3FiYiMAyN6r1trcm X1/C3H+6sGS909/19eh90n11SGCurxGqsEshmVZGEq/ybntDNMeC6anIDAsRlRUo/rRO Yg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphjs545-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUFq0aJ032541; Tue, 30 Nov 2021 16:07:14 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 3cnphjs533-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +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 1AUG3Zm2005071; Tue, 30 Nov 2021 16:07:13 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 3ckcabfu4c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:13 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7BsH41025856 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:11 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E047DB2077; Tue, 30 Nov 2021 16:07:10 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C2DE6B207B; Tue, 30 Nov 2021 16:07:10 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:10 +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: [RFC 02/20] ima: Define ns_status for storing namespaced iint data Date: Tue, 30 Nov 2021 11:06:36 -0500 Message-Id: <20211130160654.1418231-3-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: PXRV5Zl_xFoFiOd1yZYA0FSl3wUwW5qe X-Proofpoint-ORIG-GUID: DKBVaJqCcb6_9UrbsE4fgFeKfimsYMe5 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 spamscore=0 priorityscore=1501 mlxscore=0 adultscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 lowpriorityscore=0 bulkscore=0 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 3 + security/integrity/ima/Makefile | 1 + security/integrity/ima/ima.h | 24 +++++ security/integrity/ima/ima_init_ima_ns.c | 9 ++ security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_ns_status.c | 132 +++++++++++++++++++++++ 6 files changed, 170 insertions(+) create mode 100644 security/integrity/ima/ima_ns_status.c diff --git a/include/linux/ima.h b/include/linux/ima.h index 86d126b9ff2f..cc0e8c509fa2 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -214,6 +214,9 @@ static inline int ima_inode_removexattr(struct dentry *dentry, struct ima_namespace { struct kref kref; struct user_namespace *user_ns; + 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 12723d77fe17..1a44963e8ba9 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -14,9 +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 fa8069acc217..b10d92959033 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -61,6 +61,7 @@ struct ima_namespace *copy_ima_ns(struct ima_namespace *old_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..b143514c2cb1 --- /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; +} + +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 Tue Nov 30 16:06:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647689 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 125A0C4332F for ; Tue, 30 Nov 2021 16:08:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243629AbhK3QLV (ORCPT ); Tue, 30 Nov 2021 11:11:21 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:52562 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232085AbhK3QLA (ORCPT ); Tue, 30 Nov 2021 11:11:00 -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 1AUFqbqM016508; Tue, 30 Nov 2021 16:07:17 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=xwS++TS+sofm0+dElmj92x7hvIPEbR8woYyiBUNGzb8=; b=OQmp1+UHXLtzKEXwHopNv7xcCwouHZIqPBayEe7uibyXyVYZeIzo6GBlETR/XW1kN7KO pFZLqln2a1BUvH6WPvj/PDtjW4DWI1v9PYKwhh9pOJdr9ggOkjOTUBkXKD1A5S5rgV4E OuVax5aJKHJWiNncWEFxH4QWbiLI8UK4LDtlV4E2s8E85U+koyFK2isjRpE5QRAvgQJY FwC261g9fzkV/b5zCkDvZUidCSwoxgls1Po0FnIg6mmUsVT8JnkcWmf+bFJUSoHTaAxy 9FoC9/4M+kdXJjgYvgGM5ivgMV5sjvtM6kMgvccmql9NOURGONZ5tuMLzUtjtbdTKTX3 EQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpyygb8f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUFsWQQ020274; Tue, 30 Nov 2021 16:07:16 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 3cnpyygb7s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUG3alQ031979; Tue, 30 Nov 2021 16:07:15 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 3ckcabr03f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7BYn43909566 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:11 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0FA97B2076; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E9DF8B207D; Tue, 30 Nov 2021 16:07:10 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:10 +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: [RFC 03/20] ima: Namespace audit status flags Date: Tue, 30 Nov 2021 11:06:37 -0500 Message-Id: <20211130160654.1418231-4-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: 88KhHsLTP7NBCXHeXpi6FIMLP7qrjxkl X-Proofpoint-GUID: tSmv5Sdzz-5lJATcIVIV-FxWnkFnyqym X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 mlxscore=0 suspectscore=0 impostorscore=0 bulkscore=0 phishscore=0 adultscore=0 mlxlogscore=999 clxscore=1015 malwarescore=0 priorityscore=1501 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 24 +++++++++++++++++------- security/integrity/ima/ima_ns.c | 20 ++++++++++++++++++++ 5 files changed, 67 insertions(+), 11 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 598baf451a54..d8edd1c03de8 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1250,6 +1250,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..4df60dbb56f7 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -204,6 +204,7 @@ static int process_measurement(struct file *file, const struct cred *cred, { 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 +217,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 +246,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(get_current_ns(), inode); + if (IS_ERR(status)) + rc = PTR_ERR(status); + } } if (!rc && violation_check) @@ -259,11 +267,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 +284,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 +292,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 +369,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 b10d92959033..1c23dc1b8100 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -75,6 +75,26 @@ void free_ima_ns(struct kref *kref) 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; +} + int __init imans_cache_init(void) { imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); From patchwork Tue Nov 30 16:06:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647695 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 435CEC433FE for ; Tue, 30 Nov 2021 16:08:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243690AbhK3QL0 (ORCPT ); Tue, 30 Nov 2021 11:11:26 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:58968 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243438AbhK3QLA (ORCPT ); Tue, 30 Nov 2021 11:11:00 -0500 Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFQGxT028854; Tue, 30 Nov 2021 16:07:15 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=3Xbkz6SmCOX+TufTGXIiM8B5gEQC0MSmlPHKriIJrhc=; b=jFb+Nla0ZBBc8aYlUGhceVHDHkkFYxCDOvhAtI3NgnJimLZePIip20vZNMsKEhJBqMqk A44vfrhKFp3pt62g9JGiXmgKVA/hkIiCLs0CUC9umdwZqI1ggdkO9LzL7KCSK89DCgA4 JIg43XhBX/zM4Tl0ed6pdRqk2G35XGCGN5k8t1wmlOP8mrHTrThhur/R/ns3z3d30abu KLe1o+cWpWSDmDVeTrBSw6Uapw7DqK2F0BDcilqKRdR3kDur0uLIC1jeVlIz5zkF2Q0S aDkZ28diKjIbJ+ugYC9adhpWxhvlL/42GuEuU7H3Q8zIRUjMnBUliXsEf6i1bauFJmgl jw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphj14p5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +0000 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFSRsM006557; Tue, 30 Nov 2021 16:07:14 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 3cnphj14nk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +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 1AUG43PE014699; Tue, 30 Nov 2021 16:07:13 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 3ckcabfx2f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:13 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7BLl42270980 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:11 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3321FB2080; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1A0D6B206A; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 04/20] ima: Move delayed work queue and variables into ima_namespace Date: Tue, 30 Nov 2021 11:06:38 -0500 Message-Id: <20211130160654.1418231-5-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: q0F9xS-b33ihaYD4RKeKhtl7ZFkYK0C- X-Proofpoint-GUID: Tyz2-dxqCC8eOlbz92RMlETtoz5Bp7Vu X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 clxscore=1015 adultscore=0 mlxscore=0 suspectscore=0 phishscore=0 malwarescore=0 spamscore=0 bulkscore=0 priorityscore=1501 lowpriorityscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 3 ++- 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, 44 insertions(+), 30 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index cc0e8c509fa2..4b5dada581e4 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -217,6 +217,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..b89cd69df0de 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" @@ -430,7 +431,7 @@ static int ima_release_policy(struct inode *inode, struct file *file) return 0; } - ima_update_policy(); + ima_update_policy(get_current_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 1a44963e8ba9..3bc2d3611739 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 Tue Nov 30 16:06:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647699 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 5505AC433FE for ; Tue, 30 Nov 2021 16:08:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243708AbhK3QL2 (ORCPT ); Tue, 30 Nov 2021 11:11:28 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:20054 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243464AbhK3QLA (ORCPT ); Tue, 30 Nov 2021 11:11:00 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkTrA019625; Tue, 30 Nov 2021 16:07:20 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=sdx2ghYnAySCVdipD9SeJ9FQ4PSdwB9xcnyBgKS1RQg=; b=b2jzwkoax/NlfDsFt8M+s9kSdjUdKT/bzRAmJ1X/MTcnxl+S3Ol3uQFE16Q2utJgKO+z G8bieucN4+e0IZq2lvylEff+1MGDYpoFgt9sLxvhba8g4h0PgPxvS4V7iwqihd7YA7fw c1E1gEshX+NyENNJyxwH43z1QrDaZ8cxsDzUeRTti6Tbxibow8ywnD+sEYPM4vYEZyWM geOBwG5tuZATlW951yMbagD/FVlr+CZ9U8fBWE+C6IRZC4jh+ZedC5GTbkCR+KLHnVM8 SvYlw1w4E010Zs3UsftjI8ks9xnFP8vv1eKz11DG2zH/M/VvrYMV8udN5Yp+HW12KOYS MA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghx1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:20 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFlKQ2025596; Tue, 30 Nov 2021 16:07:19 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 3cnpw4ghw1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:19 +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 1AUG3aah031982; Tue, 30 Nov 2021 16:07:17 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 3ckcabr03r-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7B5Z50921840 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:11 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5741DB205F; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3E75EB2089; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 05/20] ima: Move IMA's keys queue related variables into ima_namespace Date: Tue, 30 Nov 2021 11:06:39 -0500 Message-Id: <20211130160654.1418231-6-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: aM3h58fkw26NaYqI84b0aLqHP-FBVxuC X-Proofpoint-ORIG-GUID: WgmfUvO_AqdjuaP4Z3IG3HkDZ5iYw32D X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 4b5dada581e4..977df9155cde 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -219,6 +219,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 3bc2d3611739..7b66fe598789 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -45,5 +45,10 @@ int __init ima_ns_init(void) struct ima_namespace init_ima_ns = { .kref = KREF_INIT(1), .user_ns = &init_user_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 1c23dc1b8100..4de4a93bc009 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -38,6 +38,12 @@ static struct ima_namespace *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 + return ns; fail_free: 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 Tue Nov 30 16:06:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647703 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 D1DBCC433FE for ; Tue, 30 Nov 2021 16:08:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243528AbhK3QLd (ORCPT ); Tue, 30 Nov 2021 11:11:33 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:5608 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243475AbhK3QLB (ORCPT ); Tue, 30 Nov 2021 11:11:01 -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 1AUFQErS010515; Tue, 30 Nov 2021 16:07:17 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=H5V2VSgjWhBEOPvaIsvv0HjNvQ1HtR4upQsq6UQBLd8=; b=PMTqBxtzSm7WE8IlGs51IKS9o78vMhsVhShyKf/SDQMQkeWzy7V+jhgK16d5T092SgFP 4k6To9VkT5x3mkOdUw1nQEF2vBtiqrjWRMrOXGOl3hDjszY5BFIRbBBqbLgV1m5BJDeX iX7vqraBOLxCKsV849BgG2qZ9NrTjiO06/efTp2d/hBbPgfeFcySxiubFEoDZwqhad2Q HZ+1EEACb/MT+XDdCc5VG2M7k5XpMlO6LID7fAM9K5I1k7ayYSb/Lpjb1Nvzf2uyRJqx ZvoJPQ8O/BQmCmVW1emPN3yAUCK0juhBx/tIy+Ep4aE6hBACrB0ndymE5bx+vnNSGJm2 XQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphjs552-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUFq0aM032541; Tue, 30 Nov 2021 16:07:16 GMT Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphjs548-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1AUG4C51003741; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma05wdc.us.ibm.com with ESMTP id 3ckcaayt9u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7C6O41156992 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 91AEFB206E; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 66236B2074; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 06/20] ima: Move policy related variables into ima_namespace Date: Tue, 30 Nov 2021 11:06:40 -0500 Message-Id: <20211130160654.1418231-7-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 2PeVIkhqpRxz_qsPMoubRHvBJKqKa9Uv X-Proofpoint-ORIG-GUID: W9kZEjfS2MyzQDRAFGkhxYo1XLUmW4VO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 spamscore=0 priorityscore=1501 mlxscore=0 adultscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 lowpriorityscore=0 bulkscore=0 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 13 +- 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 | 11 +- security/integrity/ima/ima_init.c | 2 +- security/integrity/ima/ima_init_ima_ns.c | 6 + security/integrity/ima/ima_main.c | 68 +++++----- security/integrity/ima/ima_ns.c | 1 + security/integrity/ima/ima_policy.c | 128 ++++++++++--------- security/integrity/ima/ima_queue_keys.c | 2 +- 12 files changed, 178 insertions(+), 125 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 977df9155cde..e782b00710ad 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -82,7 +82,8 @@ static inline int ima_file_check(struct file *file, int mask) return 0; } -static inline void ima_post_create_tmpfile(struct user_namespace *mnt_userns, +static inline void ima_post_create_tmpfile(struct ima_namespace *ns, + struct user_namespace *mnt_userns, struct inode *inode) { } @@ -239,9 +240,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..b5fe4ed62fec 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(get_current_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 b89cd69df0de..fc0413c8c358 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -297,7 +297,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(get_current_ns(), p); if (rc < 0) break; size -= rc; @@ -345,7 +345,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(get_current_ns(), data); } mutex_unlock(&ima_write_mutex); out_free: @@ -411,11 +411,12 @@ 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); - if (valid_policy && ima_check_policy() < 0) { + if (valid_policy && ima_check_policy(ns) < 0) { cause = "failed"; valid_policy = 0; } @@ -425,13 +426,13 @@ 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; } - ima_update_policy(get_current_ns()); + 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 24848373a061..2ec9a22bbddf 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -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 7b66fe598789..2d644791a795 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 4df60dbb56f7..9cf1fd7c70bf 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -188,7 +188,7 @@ void ima_file_free(struct file *file) struct inode *inode = file_inode(file); struct integrity_iint_cache *iint; - if (!ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!get_current_ns()->ima_policy_flag || !S_ISREG(inode->i_mode)) return; iint = integrity_iint_find(inode); @@ -198,7 +198,8 @@ 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) { @@ -219,18 +220,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; @@ -248,7 +249,7 @@ static int process_measurement(struct file *file, const struct cred *cred, rc = -ENOMEM; if (!rc && (action & IMA_NS_STATUS_ACTIONS)) { - status = ima_get_ns_status(get_current_ns(), inode); + status = ima_get_ns_status(ns, inode); if (IS_ERR(status)) rc = PTR_ERR(status); } @@ -356,7 +357,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, @@ -419,7 +420,8 @@ int ima_file_mmap(struct file *file, unsigned long prot) if (file && (prot & PROT_EXEC)) { security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, + return process_measurement(get_current_ns(), + file, current_cred(), secid, NULL, 0, MAY_EXEC, MMAP_CHECK); } @@ -440,6 +442,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]; @@ -452,13 +455,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); @@ -498,13 +501,13 @@ int ima_bprm_check(struct linux_binprm *bprm) u32 secid; security_task_getsecid_subj(current, &secid); - ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, + ret = process_measurement(get_current_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(get_current_ns(), bprm->file, bprm->cred, secid, NULL, 0, MAY_EXEC, CREDS_CHECK); } @@ -523,18 +526,19 @@ int ima_file_check(struct file *file, int mask) u32 secid; security_task_getsecid_subj(current, &secid); - return process_measurement(file, current_cred(), secid, NULL, 0, + return process_measurement(get_current_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); @@ -587,7 +591,7 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) if (!file) return -EINVAL; - return __ima_inode_hash(file_inode(file), buf, buf_size); + return __ima_inode_hash(get_current_ns(), file_inode(file), buf, buf_size); } EXPORT_SYMBOL_GPL(ima_file_hash); @@ -614,7 +618,7 @@ int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) if (!inode) return -EINVAL; - return __ima_inode_hash(inode, buf, buf_size); + return __ima_inode_hash(get_current_ns(), inode, buf, buf_size); } EXPORT_SYMBOL_GPL(ima_inode_hash); @@ -630,13 +634,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; @@ -662,14 +667,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; @@ -720,7 +726,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(get_current_ns(), file, current_cred(), secid, NULL, 0, MAY_READ, func); } @@ -763,7 +769,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(get_current_ns(), file, current_cred(), secid, buf, size, MAY_READ, func); } @@ -869,7 +875,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, @@ -897,7 +904,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(); @@ -916,7 +923,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) @@ -953,7 +960,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); @@ -996,7 +1003,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(get_current_ns(), + file_mnt_user_ns(f.file), file_inode(f.file), buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, NULL, false, NULL, 0); fdput(f); @@ -1029,7 +1037,7 @@ int ima_measure_critical_data(const char *event_label, 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(get_current_ns(), &init_user_ns, NULL, buf, buf_len, event_name, CRITICAL_DATA, 0, event_label, hash, digest, digest_len); @@ -1062,7 +1070,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 4de4a93bc009..709db86f285f 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -67,6 +67,7 @@ struct ima_namespace *copy_ima_ns(struct ima_namespace *old_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..96e7d63167e8 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; @@ -477,7 +471,7 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, if (event != LSM_POLICY_CHANGE) return NOTIFY_DONE; - ima_lsm_update_rules(); + ima_lsm_update_rules(get_current_ns()); return NOTIFY_OK; } @@ -688,7 +682,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 +697,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 +755,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 +792,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 +808,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 +818,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 +826,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 +839,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 +870,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 +888,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 +918,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 +930,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 +942,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 +985,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 +1001,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 +1074,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 +1095,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 +1322,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 +1673,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 +1809,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 +1833,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 +1842,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 +1853,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); } @@ -1890,7 +1901,7 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) struct list_head *ima_rules_tmp; rcu_read_lock(); - ima_rules_tmp = rcu_dereference(ima_rules); + ima_rules_tmp = rcu_dereference(get_current_ns()->ima_rules); list_for_each_entry_rcu(entry, ima_rules_tmp, list) { if (!l--) { rcu_read_unlock(); @@ -1904,14 +1915,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) @@ -2177,7 +2189,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(get_current_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 Tue Nov 30 16:06:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647681 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 4D6C1C43217 for ; Tue, 30 Nov 2021 16:07:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243579AbhK3QLQ (ORCPT ); Tue, 30 Nov 2021 11:11:16 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:13564 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243416AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkWuq019780; Tue, 30 Nov 2021 16:07:17 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=vnrZ/v2/umeiqe3QaMFXKuW0ci1n67xWqMD6UYz96O8=; b=OGzb6jxs8uj31jU1JbjOZdiA9+CzoLEI9oG+iA4ZU7CjCtgFeCbibxScJ/rTKcXUGGH1 e/VDRChdrqa7ZIWK/gBVaVUKV1rAuMJjV5AeNaMrPWsk+lK5F2KsZCXXNdqVD6pMhUhm NOGYX8SBIn/vcuE+TZEbe78c0aOnVxwGR3z1PaZgv3ySk5zG9SC6aE0KTyCd6W29cFXz c2X3KTobmSlrXqPmdRMx2mRhvq3i/2dClGk2T/P57/ZyYGtqyK5ZYWOt69Q9OpjuUA1c jppuOPk5YNE/bOAxDawBeUyHXKDburVJxF2Mfy6LK5Wxkw4UO2WcP9v14jH+mPVWaxkC fg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghum-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFkXTe019856; Tue, 30 Nov 2021 16:07:16 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 3cnpw4ghtx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG2pKj024654; Tue, 30 Nov 2021 16:07:14 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 3cnne1b9uk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7C7F49742210 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:13 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C2656B208F; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9D771B2082; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 07/20] ima: Move ima_htable into ima_namespace Date: Tue, 30 Nov 2021 11:06:41 -0500 Message-Id: <20211130160654.1418231-8-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: RMew2CsO0ZGfuzwuF8arraUre0QessRw X-Proofpoint-ORIG-GUID: gNUtBF_abFSfuvN1StJiwwWzk8Pa-qb1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Move ima_htable into ima_namespace. This way the 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_main.c | 13 ++++---- security/integrity/ima/ima_queue.c | 42 ++++++++++++++---------- security/integrity/ima/ima_template.c | 4 +-- 9 files changed, 78 insertions(+), 60 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index e782b00710ad..96254dfacfa0 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -212,6 +212,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 kref kref; struct user_namespace *user_ns; @@ -249,6 +258,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 fc0413c8c358..9df8648ad64d 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 2ec9a22bbddf..6104d5116a7f 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 2d644791a795..e13adc3287ed 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_main.c b/security/integrity/ima/ima_main.c index 9cf1fd7c70bf..d692c9d53a98 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"); } @@ -256,7 +257,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); @@ -353,7 +354,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)) { @@ -969,7 +970,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 Tue Nov 30 16:06:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647697 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 3076EC4167B for ; Tue, 30 Nov 2021 16:08:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243470AbhK3QL1 (ORCPT ); Tue, 30 Nov 2021 11:11:27 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:62222 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243422AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFQEm4030045; Tue, 30 Nov 2021 16:07:16 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=NP7PlBCFVpFE1Mljfz8GtlJMMzjEnDo4ZahDN3E9Jf4=; b=nXNP5RN+QXJ3I3tm8myVSqKkvbfRpUn61vktoDokM8sHMjlcN0iO9JIVHoULSJ0FMffY OMF36MeogFpHtZjrz2gDOK+OBHRh8/IrLoWNthNsk6KSM6vH70mOMb8hnr7jiBHOTNbk zf6brrHoJUjCRzZ3BVlw8X73iS47+NzmCeEbJgYo8rdp0xYJgNy572weNkUHcWRTmh/g f+kQqofHQCXv3pWg1IoocdsPtx06EMh8247eds0nT1ut/MeN9KTbPUjW+0SVr80a3icI cbQ5B/nrAZLQUnGhcW90gI1otxMUv+zHSF0kTLEk1T3mj/DOmV1Fu+YjJZkwRAV5h9Dc Wg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphg93vt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +0000 Received: from m0098404.ppops.net (m0098404.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFR7hx000579; Tue, 30 Nov 2021 16:07:15 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 3cnphg93uu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG41NK003119; Tue, 30 Nov 2021 16:07:13 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma01wdc.us.ibm.com with ESMTP id 3ckcaayqur-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:13 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7CMv52166924 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ED489B208B; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CDBAEB2094; Tue, 30 Nov 2021 16:07:11 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 08/20] ima: Move measurement list related variables into ima_namespace Date: Tue, 30 Nov 2021 11:06:42 -0500 Message-Id: <20211130160654.1418231-9-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: py8RSZdOUXJIw3JbBbmb82gRhrvLq-VP X-Proofpoint-ORIG-GUID: 037QkWHcEx4wIArgA44Bu6b3ABbMs_x- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 impostorscore=0 suspectscore=0 phishscore=0 clxscore=1015 priorityscore=1501 malwarescore=0 bulkscore=0 lowpriorityscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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_ns.c | 1 + security/integrity/ima/ima_queue.c | 33 ++++++++++++++---------- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 96254dfacfa0..850a513834d2 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -260,6 +260,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 9df8648ad64d..c35e15fb313f 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 e13adc3287ed..57e46a10c001 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_ns.c b/security/integrity/ima/ima_ns.c index 709db86f285f..e4f4cf84a6b5 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -69,6 +69,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 Tue Nov 30 16:06:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647673 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 885D5C4332F for ; Tue, 30 Nov 2021 16:07:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243525AbhK3QLK (ORCPT ); Tue, 30 Nov 2021 11:11:10 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:30882 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243347AbhK3QK6 (ORCPT ); Tue, 30 Nov 2021 11:10:58 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkTfn019632; Tue, 30 Nov 2021 16:07:16 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=VYTWPfSyYwFG1xQaOzLT/ijBvyXA7xomQX6MzJY2mjU=; b=UyoJ09uWom/qA0ijXuLPbE8tOpIiHtXj8t3lZDhLQaV+5myL8hccDRUgPLBplitddYF+ an3h+N2Im4juRtEXgmto3saWj8R4TZ9OYNIm7Q+0rgW4rDn7bitMoOi1mtw65Zno5Cgn /5W3MsdUnJwE0gg7eAwVoKij+Hp2f22WWtDSDg+zd6EwHxwAFGJlXP1NDutJSLFRtx4G YxsY08EsKTghJlplmKwxRJBU6uxNVyGUKvscq+VGI8hhL5MU2LNQEZdSEJhKQLIW9l7A yy6h8rArRXMLC3dy/7q/6aekfKS9oh3jOZ+rdYQ7rkVHYduA1KRyrFNn5/n1cqYesCCl 8Q== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghu2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFkern020776; Tue, 30 Nov 2021 16:07:15 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 3cnpw4ghtf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG2paM024665; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma04dal.us.ibm.com with ESMTP id 3cnne1b9u1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7CVs49348926 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 16271B2066; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 03785B208D; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:11 +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: [RFC 09/20] ima: Only accept AUDIT rules for IMA non-init_ima_ns namespaces for now Date: Tue, 30 Nov 2021 11:06:43 -0500 Message-Id: <20211130160654.1418231-10-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: b8H8dcfk5eYtv4zzaqlVmaKST0LR6vLs X-Proofpoint-ORIG-GUID: RWm9cdsZnXOupI1zgprMl9H67BC9ecPA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 96e7d63167e8..02e96da2faff 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1785,6 +1785,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 Tue Nov 30 16:06:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647671 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 A6E7BC433EF for ; Tue, 30 Nov 2021 16:07:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243495AbhK3QLI (ORCPT ); Tue, 30 Nov 2021 11:11:08 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:26506 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243202AbhK3QK6 (ORCPT ); Tue, 30 Nov 2021 11:10:58 -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 1AUFlVUC001271; Tue, 30 Nov 2021 16:07:16 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=ORsOqvHhu0hXyxnTJElDo6KuCG4EgLSfJ6yy5k2gfw0=; b=VgMVrDP7fCKiBOSPEoeJYN7t3DP//ACcp3lEfSgFlEIsO1vQWkm87557pT6ArP4TC9kj pUeEMcq4Q3iw3dk2ZLP4rJI74qm4xMpKHlvZbysdhxBDgqPzjs7jRdUQozzrkWKxZZ9S bAnkpJlOPpCl5RefK9nl/0LoiVlxxQwqvBYwTPDQ4SosepbNt55KYkq4v9B7D7bTU7X1 sqzntdNRXVylcuuTULopH9Br3vtIldELHVTnWJhHtCq8EBZeoADWfEyCqJ6SawRL9t5Y AV4R9J+W4So7o6/+hp4s43tVPoUnFY6mmVecqpCQ+JJueyXqxG5JlXXde6arUQMe6g+k iA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpwm0gve-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUFn00t005435; Tue, 30 Nov 2021 16:07:15 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 3cnpwm0gv0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG4NsE023584; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma02dal.us.ibm.com with ESMTP id 3cn5ey2826-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7C2852166926 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 356CEB209E; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 203B4B2074; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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: [RFC 10/20] ima: Implement hierarchical processing of file accesses Date: Tue, 30 Nov 2021 11:06:44 -0500 Message-Id: <20211130160654.1418231-11-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: olY2uukC-vW7BjoKv2512FBOJzNLKugZ X-Proofpoint-GUID: hI2lGVSoQuVVRbQEZhUSuTO6kUvtS6v4 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 malwarescore=0 mlxlogscore=999 spamscore=0 priorityscore=1501 lowpriorityscore=0 suspectscore=0 impostorscore=0 adultscore=0 bulkscore=0 clxscore=1015 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 --- security/integrity/ima/ima_main.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index d692c9d53a98..42cbcaf2dc1e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -199,10 +199,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; @@ -404,6 +404,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) +{ + int ret = 0; + struct user_namespace *user_ns; + + do { + ret = _process_measurement(ns, file, cred, secid, buf, size, mask, func); + if (ret) + break; + user_ns = ns->user_ns->parent; + if (!user_ns) + break; + ns = user_ns->ima_ns; + } while (1); + + return ret; +} + /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) From patchwork Tue Nov 30 16:06:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647693 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 E25D7C43217 for ; Tue, 30 Nov 2021 16:08:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243645AbhK3QLX (ORCPT ); Tue, 30 Nov 2021 11:11:23 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:13406 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243435AbhK3QLA (ORCPT ); Tue, 30 Nov 2021 11:11:00 -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 1AUFlXpT001758; Tue, 30 Nov 2021 16:07:16 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=k87Qh4JL58PaoWjNxP/QguzWPYNVZIv9+Y+W20HNtnw=; b=TzgE3B6B2rL5kO2qjyusvL0XhJhbp8IAb1AAjqvbIBYUVLgzjGMk+8WcRGL0IiBNaxwR lfSBeS653bbrbbDeavC/LR1Od2obnw/SfbYOpeVHihwDiwlEh/F9j4H2H1DYIDZemlZB Vu4h/L0SljfvgfrMC9KX4KxyUb6meK43fGgX0LrxaA4LDBADU1VQCqttfE6KJt++zn4N ImbhjXpgV2vfoAZ6MFpn8DUVKH0ZmrrF+aVqakVBY+GK5xVAoUlH4nycAMWUJWaxgJrM /NRCfkBgnl1Xepq7oUibMQX7FPYE1v/KY09a8GCO5oFV93zYRHRrVZxKCkVuce4rRBW9 QA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpwm0gvh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUFm61Z003286; Tue, 30 Nov 2021 16:07:15 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 3cnpwm0guw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG2j4x009853; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma02wdc.us.ibm.com with ESMTP id 3ckcab7tjv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7Ck754919658 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 53ACDB20A9; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3FC03B2095; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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: [RFC 11/20] securityfs: Prefix global variables with securityfs_ Date: Tue, 30 Nov 2021 11:06:45 -0500 Message-Id: <20211130160654.1418231-12-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: SzPnfeCdJ1Gj2rHiauPRxSbAkUUzGn4e X-Proofpoint-GUID: qiRaAPH9iTBG7hniYl5_31WY5hDaHatM X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 malwarescore=0 mlxlogscore=999 spamscore=0 priorityscore=1501 lowpriorityscore=0 suspectscore=0 impostorscore=0 adultscore=0 bulkscore=0 clxscore=1015 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Prefix global variables 'mount' and 'mount_count' with securityfs_ so they are easier to distinguish as variables belonging to securityfs rather than variables being passed in through new APIs we will introduce. Signed-off-by: Stefan Berger --- security/inode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/security/inode.c b/security/inode.c index 6c326939750d..e523829c22cb 100644 --- a/security/inode.c +++ b/security/inode.c @@ -22,8 +22,8 @@ #include #include -static struct vfsmount *mount; -static int mount_count; +static struct vfsmount *securityfs_mount; +static int securityfs_mount_count; static void securityfs_free_inode(struct inode *inode) { @@ -66,7 +66,7 @@ static int securityfs_init_fs_context(struct fs_context *fc) return 0; } -static struct file_system_type fs_type = { +static struct file_system_type securityfs_type = { .owner = THIS_MODULE, .name = "securityfs", .init_fs_context = securityfs_init_fs_context, @@ -118,12 +118,12 @@ 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); + error = simple_pin_fs(&securityfs_type, &securityfs_mount, &securityfs_mount_count); if (error) return ERR_PTR(error); if (!parent) - parent = mount->mnt_root; + parent = securityfs_mount->mnt_root; dir = d_inode(parent); @@ -168,7 +168,7 @@ 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); + simple_release_fs(&securityfs_mount, &securityfs_mount_count); return dentry; } @@ -309,7 +309,7 @@ void securityfs_remove(struct dentry *dentry) dput(dentry); } inode_unlock(dir); - simple_release_fs(&mount, &mount_count); + simple_release_fs(&securityfs_mount, &securityfs_mount_count); } EXPORT_SYMBOL_GPL(securityfs_remove); @@ -336,7 +336,7 @@ static int __init securityfs_init(void) if (retval) return retval; - retval = register_filesystem(&fs_type); + retval = register_filesystem(&securityfs_type); if (retval) { sysfs_remove_mount_point(kernel_kobj, "security"); return retval; From patchwork Tue Nov 30 16:06:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647685 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 8351BC4167E for ; Tue, 30 Nov 2021 16:08:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243620AbhK3QLS (ORCPT ); Tue, 30 Nov 2021 11:11:18 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:13532 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243428AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0187473.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFwm63001599; Tue, 30 Nov 2021 16:07:17 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=XHDx7UdQiacDIyoRj9REkK48bjlrza6iLsK3SdP+asw=; b=NtRDpjLHifqbeRYVpYCrF83O3ZtekvaCGOkX9E4NfplvmKuUE+lnrRiQGRM7v/Fn5UG2 BLyqea0V0cP0E3u2DSBo7rjvyTJBtPdrjqo7xdRj9Us4THt+4Bb9ZPq8l/T6sE/dnQcu nEwQ84sFGJEKGirO1LL2VTUGDmu17CTVnwJjI1VhlCpO79REy+Hx80ITsoj8O9apaFsj ckvKTYVdoAT/nAEGAovGig65KvtBJ1mqQ50gRlXnv76rvUuxNyXlzZv+l3dSFfpTm1sU 9svEr/tp7/krk0BO50cuJUoC9pBJNRjFzRB0iLLQI76F/wG2aZTrzNTOtWkju0i/K2pO qA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnq2tg74q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from m0187473.ppops.net (m0187473.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUG1c0e015672; Tue, 30 Nov 2021 16:07:16 GMT Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnq2tg73u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1AUG4BYV003706; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma05wdc.us.ibm.com with ESMTP id 3ckcaayt9e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7CFQ54919660 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7782DB2099; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5E9B1B20AB; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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: [RFC 12/20] securityfs: Pass static variables as parameters from top level functions Date: Tue, 30 Nov 2021 11:06:46 -0500 Message-Id: <20211130160654.1418231-13-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: Hb-f_ErIIfmDCMsYp0rKOLRlJ6Mvg7TO X-Proofpoint-ORIG-GUID: 3MsJDVwPzPblJM5bZQD5SckRyV7Z42Gf X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 mlxscore=0 impostorscore=0 adultscore=0 phishscore=0 bulkscore=0 priorityscore=1501 spamscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Pass the securityfs_-prefixed static variables from current top level functions so that new APIs allow callers to pass in similar parameters and thus share most of the existing functions. Signed-off-by: Stefan Berger --- security/inode.c | 95 +++++++++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/security/inode.c b/security/inode.c index e523829c22cb..429744ff4ab3 100644 --- a/security/inode.c +++ b/security/inode.c @@ -88,6 +88,11 @@ static struct file_system_type securityfs_type = { * this file. * @iops: a point to a struct of inode_operations that should be used for * this file/dir + * @mount: a pointer to a pointer for existing vfsmount to use or for + * one to create + * @mount_count: pointer to integer for mount_count that goes along with + * @mount + * * * This is the basic "create a file/dir/symlink" function for * securityfs. It allows for a wide range of flexibility in creating @@ -107,7 +112,9 @@ static struct file_system_type securityfs_type = { static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops, - const struct inode_operations *iops) + const struct inode_operations *iops, + struct file_system_type *fs_type, + struct vfsmount **mount, int *mount_count) { struct dentry *dentry; struct inode *dir, *inode; @@ -118,12 +125,12 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, pr_debug("securityfs: creating file '%s'\n",name); - error = simple_pin_fs(&securityfs_type, &securityfs_mount, &securityfs_mount_count); + error = simple_pin_fs(fs_type, mount, mount_count); if (error) return ERR_PTR(error); if (!parent) - parent = securityfs_mount->mnt_root; + parent = (*mount)->mnt_root; dir = d_inode(parent); @@ -168,7 +175,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, dentry = ERR_PTR(error); out: inode_unlock(dir); - simple_release_fs(&securityfs_mount, &securityfs_mount_count); + simple_release_fs(mount, mount_count); return dentry; } @@ -201,7 +208,9 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) { - return securityfs_create_dentry(name, mode, parent, data, fops, NULL); + return securityfs_create_dentry(name, mode, parent, data, fops, NULL, + &securityfs_type, &securityfs_mount, + &securityfs_mount_count); } EXPORT_SYMBOL_GPL(securityfs_create_file); @@ -231,6 +240,29 @@ struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) } EXPORT_SYMBOL_GPL(securityfs_create_dir); +struct dentry *_securityfs_create_symlink(const char *name, + struct dentry *parent, + const char *target, + const struct inode_operations *iops, + struct file_system_type *fs_type, + struct vfsmount **mount, int *mount_count) +{ + struct dentry *dent; + char *link = NULL; + + if (target) { + link = kstrdup(target, GFP_KERNEL); + if (!link) + return ERR_PTR(-ENOMEM); + } + dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, + link, NULL, iops, fs_type, + mount, mount_count); + if (IS_ERR(dent)) + kfree(link); + + return dent; +} /** * securityfs_create_symlink - create a symlink in the securityfs filesystem * @@ -262,37 +294,13 @@ struct dentry *securityfs_create_symlink(const char *name, const char *target, const struct inode_operations *iops) { - struct dentry *dent; - char *link = NULL; - - if (target) { - link = kstrdup(target, GFP_KERNEL); - if (!link) - return ERR_PTR(-ENOMEM); - } - dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, - link, NULL, iops); - if (IS_ERR(dent)) - kfree(link); - - return dent; + return _securityfs_create_symlink(name, parent, target, iops, + &securityfs_type, &securityfs_mount, + &securityfs_mount_count); } EXPORT_SYMBOL_GPL(securityfs_create_symlink); -/** - * securityfs_remove - removes a file or directory from the securityfs filesystem - * - * @dentry: a pointer to a the dentry of the file or directory to be removed. - * - * This function removes a file or directory in securityfs that was previously - * created with a call to another securityfs function (like - * securityfs_create_file() or variants thereof.) - * - * This function is required to be called in order for the file to be - * removed. No automatic cleanup of files will happen when a module is - * removed; you are responsible here. - */ -void securityfs_remove(struct dentry *dentry) +void _securityfs_remove(struct dentry *dentry, struct vfsmount **mount, int *mount_count) { struct inode *dir; @@ -309,8 +317,27 @@ void securityfs_remove(struct dentry *dentry) dput(dentry); } inode_unlock(dir); - simple_release_fs(&securityfs_mount, &securityfs_mount_count); + simple_release_fs(mount, mount_count); +} + +/** + * securityfs_remove - removes a file or directory from the securityfs filesystem + * + * @dentry: a pointer to a the dentry of the file or directory to be removed. + * + * This function removes a file or directory in securityfs that was previously + * created with a call to another securityfs function (like + * securityfs_create_file() or variants thereof.) + * + * This function is required to be called in order for the file to be + * removed. No automatic cleanup of files will happen when a module is + * removed; you are responsible here. + */ +void securityfs_remove(struct dentry *dentry) +{ + _securityfs_remove(dentry, &securityfs_mount, &securityfs_mount_count); } + EXPORT_SYMBOL_GPL(securityfs_remove); #ifdef CONFIG_SECURITY From patchwork Tue Nov 30 16:06:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647677 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 9FDBDC433F5 for ; Tue, 30 Nov 2021 16:07:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243553AbhK3QLN (ORCPT ); Tue, 30 Nov 2021 11:11:13 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:45560 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243412AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -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 1AUG1kaP030637; Tue, 30 Nov 2021 16:07:17 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=qCtGH9WkS4EeWlEopqOl7eF841IqugzFqa9zcATZsQY=; b=F0Mkch7mwlaZnq+L5tG+lWCsBahPzovFgUBW2enKXRab8OD2jwPTo4lBr/S4cYnQOoF6 lOuWXm/EFO6/tCxHinlR08QCs6MAjlY4pWu/K08vsrhkSiaZVYxqUCLQslm3+3AL0eX+ ffkiZTHVbfBQ1lMNJPC8SkDTREjde1bHun+S0ShOAxP/7060OlZ3pki/Kx/VyRMa6LtR 8GLoztDksKEpoPwnQY6PpHIxKCEguCFmU0kqewgPyjTmtPcIRxT8YH8AMoerwg3yn886 aqfGPlXtv+crvUDf2A+s9BDfZqIR0eppHssh470+XqhKAWphvRbV7WPqctrjiZ9MTObG Wg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnq48g5cr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUG6Zf8025329; Tue, 30 Nov 2021 16:07:15 GMT Received: from ppma03wdc.us.ibm.com (ba.79.3fa9.ip4.static.sl-reverse.com [169.63.121.186]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnq48g5c0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG3dQ8014090; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma03wdc.us.ibm.com with ESMTP id 3cn3k1qgsw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7CdB39780780 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:12 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AECB3B2065; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 80637B209F; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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: [RFC 13/20] securityfs: Build securityfs_ns for namespacing support Date: Tue, 30 Nov 2021 11:06:47 -0500 Message-Id: <20211130160654.1418231-14-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: _sBp7DtEQu3_8VHRTdDXWoGDVysgk-s- X-Proofpoint-ORIG-GUID: m4XWq6Zh3Hjn7wqsDqx4aWWPjgKwbmG4 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 phishscore=0 spamscore=0 malwarescore=0 clxscore=1015 mlxlogscore=999 adultscore=0 mlxscore=0 bulkscore=0 impostorscore=0 priorityscore=1501 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Implement 'securityfs_ns' 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. This filesystem shares much of the existing code of SecurityFS but requires a new API call securityfs_ns_create_mount() for creating a new instance. The API calls of securityfs_ns have the prefix securityfs_ns_ and take additional parameters struct vfsmount * and mount_count that allow for multiple instances of this filesystem to exist. The filesystem can be mounted to the usual securityfs mount point like this: mount -t securityfs_ns /sys/kernel/security /sys/kernel/security Signed-off-by: Stefan Berger --- include/linux/security.h | 18 ++++ include/uapi/linux/magic.h | 1 + security/inode.c | 197 +++++++++++++++++++++++++++++++++++-- 3 files changed, 210 insertions(+), 6 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index 7e0ba63b5dde..8e479266f544 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1929,6 +1929,24 @@ struct dentry *securityfs_create_symlink(const char *name, const struct inode_operations *iops); extern void securityfs_remove(struct dentry *dentry); +extern struct dentry *securityfs_ns_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count); +extern struct dentry *securityfs_ns_create_dir(const char *name, struct dentry *parent, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count); +struct dentry *securityfs_ns_create_symlink(const char *name, + struct dentry *parent, + const char *target, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count); +extern void securityfs_ns_remove(struct dentry *dentry, + struct vfsmount **mount, int *mount_count); +struct vfsmount *securityfs_ns_create_mount(struct user_namespace *user_ns); +extern struct vfsmount *securityfs_ns_mount; + #else /* CONFIG_SECURITYFS */ static inline struct dentry *securityfs_create_dir(const char *name, diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 35687dcb1a42..5c1cc6088dd2 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -11,6 +11,7 @@ #define CRAMFS_MAGIC_WEND 0x453dcd28 /* magic number with the wrong endianess */ #define DEBUGFS_MAGIC 0x64626720 #define SECURITYFS_MAGIC 0x73636673 +#define SECURITYFS_NS_MAGIC 0x73334473 #define SELINUX_MAGIC 0xf97cff8c #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ #define RAMFS_MAGIC 0x858458f6 /* some random number */ diff --git a/security/inode.c b/security/inode.c index 429744ff4ab3..8077d1f31489 100644 --- a/security/inode.c +++ b/security/inode.c @@ -21,6 +21,7 @@ #include #include #include +#include static struct vfsmount *securityfs_mount; static int securityfs_mount_count; @@ -73,6 +74,61 @@ static struct file_system_type securityfs_type = { .kill_sb = kill_litter_super, }; +static int securityfs_ns_fill_super(struct super_block *sb, struct fs_context *fc) +{ + static const struct tree_descr files[] = {{""}}; + int error; + + error = simple_fill_super(sb, SECURITYFS_NS_MAGIC, files); + if (error) + return error; + + sb->s_op = &securityfs_super_operations; + + return 0; +} + +static int securityfs_ns_get_tree(struct fs_context *fc) +{ + return get_tree_keyed(fc, securityfs_ns_fill_super, fc->user_ns); +} + +static const struct fs_context_operations securityfs_ns_context_ops = { + .get_tree = securityfs_ns_get_tree, +}; + +static int securityfs_ns_init_fs_context(struct fs_context *fc) +{ + fc->ops = &securityfs_ns_context_ops; + return 0; +} + +static struct file_system_type securityfs_ns_type = { + .owner = THIS_MODULE, + .name = "securityfs_ns", + .init_fs_context = securityfs_ns_init_fs_context, + .kill_sb = kill_litter_super, + .fs_flags = FS_USERNS_MOUNT, +}; + +struct vfsmount *securityfs_ns_create_mount(struct user_namespace *user_ns) +{ + struct fs_context *fc; + struct vfsmount *mnt; + + fc = fs_context_for_mount(&securityfs_ns_type, SB_KERNMOUNT); + if (IS_ERR(fc)) + return ERR_CAST(fc); + + put_user_ns(fc->user_ns); + fc->user_ns = get_user_ns(user_ns); + + mnt = fc_mount(fc); + put_fs_context(fc); + return mnt; +} + + /** * securityfs_create_dentry - create a dentry in the securityfs filesystem * @@ -155,8 +211,8 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); inode->i_private = data; if (S_ISDIR(mode)) { - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; + inode->i_op = iops ? iops : &simple_dir_inode_operations; + inode->i_fop = fops ? fops : &simple_dir_operations; inc_nlink(inode); inc_nlink(dir); } else if (S_ISLNK(mode)) { @@ -214,6 +270,41 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, } EXPORT_SYMBOL_GPL(securityfs_create_file); +/** + * securityfs_ns_create_file - create a file in the securityfs_ns filesystem + * + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * file will be created in the root of the securityfs_ns filesystem. + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + * @fops: a pointer to a struct file_operations that should be used for + * this file. + * @mount: Pointer to a pointer of a an existing vfsmount + * @mount_count: The mount_count that goes along with the @mount + * + * This function creates a file in securityfs_ns with the given @name. + * + * This function returns a pointer to a dentry if it succeeds. This + * pointer must be passed to the securityfs_ns_remove() function when the file + * is to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here). If an error occurs, the function will return + * the error value (via ERR_PTR). + */ +struct dentry *securityfs_ns_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count) +{ + return securityfs_create_dentry(name, mode, parent, data, fops, iops, + &securityfs_ns_type, mount, mount_count); +} +EXPORT_SYMBOL_GPL(securityfs_ns_create_file); + /** * securityfs_create_dir - create a directory in the securityfs filesystem * @@ -240,6 +331,34 @@ struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) } EXPORT_SYMBOL_GPL(securityfs_create_dir); +/** + * securityfs_ns_create_dir - create a directory in the securityfs_ns filesystem + * + * @name: a pointer to a string containing the name of the directory to + * create. + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * directory will be created in the root of the securityfs_ns filesystem. + * @mount: Pointer to a pointer of a an existing vfsmount + * @mount_count: The mount_count that goes along with the @mount + * + * This function creates a directory in securityfs_ns with the given @name. + * + * This function returns a pointer to a dentry if it succeeds. This + * pointer must be passed to the securityfs_ns_remove() function when the file + * is to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here). If an error occurs, the function will return + * the error value (via ERR_PTR). + */ +struct dentry *securityfs_ns_create_dir(const char *name, struct dentry *parent, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count) +{ + return securityfs_ns_create_file(name, S_IFDIR | 0755, parent, NULL, NULL, + iops, mount, mount_count); +} +EXPORT_SYMBOL_GPL(securityfs_ns_create_dir); + struct dentry *_securityfs_create_symlink(const char *name, struct dentry *parent, const char *target, @@ -263,6 +382,7 @@ struct dentry *_securityfs_create_symlink(const char *name, return dent; } + /** * securityfs_create_symlink - create a symlink in the securityfs filesystem * @@ -300,6 +420,42 @@ struct dentry *securityfs_create_symlink(const char *name, } EXPORT_SYMBOL_GPL(securityfs_create_symlink); +/** + * securityfs_ns_create_symlink - create a symlink in the securityfs_ns filesystem + * + * @name: a pointer to a string containing the name of the symlink to + * create. + * @parent: a pointer to the parent dentry for the symlink. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * directory will be created in the root of the securityfs_ns filesystem. + * @target: a pointer to a string containing the name of the symlink's target. + * If this parameter is %NULL, then the @iops parameter needs to be + * setup to handle .readlink and .get_link inode_operations. + * @iops: a pointer to the struct inode_operations to use for the symlink. If + * this parameter is %NULL, then the default simple_symlink_inode + * operations will be used. + * @mount: Pointer to a pointer of a an existing vfsmount + * @mount_count: The mount_count that goes along with the @mount + * + * This function creates a symlink in securityfs_ns with the given @name. + * + * This function returns a pointer to a dentry if it succeeds. This + * pointer must be passed to the securityfs_ns_remove() function when the file + * is to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here). If an error occurs, the function will return + * the error value (via ERR_PTR). + */ +struct dentry *securityfs_ns_create_symlink(const char *name, + struct dentry *parent, + const char *target, + const struct inode_operations *iops, + struct vfsmount **mount, int *mount_count) +{ + return _securityfs_create_symlink(name, parent, target, iops, + &securityfs_ns_type, mount, mount_count); +} +EXPORT_SYMBOL_GPL(securityfs_ns_create_symlink); + void _securityfs_remove(struct dentry *dentry, struct vfsmount **mount, int *mount_count) { struct inode *dir; @@ -340,6 +496,27 @@ void securityfs_remove(struct dentry *dentry) EXPORT_SYMBOL_GPL(securityfs_remove); +/** + * securityfs_ns_remove - removes a file or directory from the securityfs_ns filesystem + * + * @dentry: a pointer to a the dentry of the file or directory to be removed. + * @mount: Pointer to a pointer of a an existing vfsmount + * @mount_count: The mount_count that goes along with the @mount + * + * This function removes a file or directory in securityfs_ns that was previously + * created with a call to another securityfs_ns function (like + * securityfs_ns_create_file() or variants thereof.) + * + * This function is required to be called in order for the file to be + * removed. No automatic cleanup of files will happen when a module is + * removed; you are responsible here. + */ +void securityfs_ns_remove(struct dentry *dentry, struct vfsmount **mount, int *mount_count) +{ + _securityfs_remove(dentry, mount, mount_count); +} +EXPORT_SYMBOL_GPL(securityfs_ns_remove); + #ifdef CONFIG_SECURITY static struct dentry *lsm_dentry; static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count, @@ -364,14 +541,22 @@ static int __init securityfs_init(void) return retval; retval = register_filesystem(&securityfs_type); - if (retval) { - sysfs_remove_mount_point(kernel_kobj, "security"); - return retval; - } + if (retval) + goto remove_mount; + retval = register_filesystem(&securityfs_ns_type); + if (retval) + goto unregister_filesystem; #ifdef CONFIG_SECURITY lsm_dentry = securityfs_create_file("lsm", 0444, NULL, NULL, &lsm_ops); #endif return 0; + +unregister_filesystem: + unregister_filesystem(&securityfs_type); +remove_mount: + sysfs_remove_mount_point(kernel_kobj, "security"); + + return retval; } core_initcall(securityfs_init); From patchwork Tue Nov 30 16:06:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647669 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 DA8B8C433EF for ; Tue, 30 Nov 2021 16:07:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240545AbhK3QK6 (ORCPT ); Tue, 30 Nov 2021 11:10:58 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:35484 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239413AbhK3QK4 (ORCPT ); Tue, 30 Nov 2021 11:10:56 -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 1AUG1kaT030637; Tue, 30 Nov 2021 16:07:21 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=RU8AD7j4gnQ3rwQKYEYUcU8OEsk/roLIGg4Xm8W4ETI=; b=Mh9GmPosYMcG8826zOZa7I2nhcl7OdT9n10ctw41FApF06OkbxYGUA4tn5ysfYNo8efW hkTWRINkJ9fJOYptd6rSzLcQ9ZvytE+wWSqD3b+J6Hni6dqmWACy97SMXjzJCJh0KUM4 USux3CMMhMF7X7nUAouRKr2u1IvdSXpwsnqilhHF0CLg+/sZbT/zL8ySrkpk6Cew4/+f IAemEF1VJdrEu1DgYJnc+1mtAlqh7yPH+c4vLOrz1EeTdKCQRVWwx35VSi24iymwLl3n srjfZzsoOm7ZIHjvv3WmfJ4WykDrhIY1S/uVZgiONdBOiNoA5QS/fLCCEvVR/3XJvXBC og== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnq48g5fa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:20 +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 1AUG2TuQ000348; Tue, 30 Nov 2021 16:07:20 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 3cnq48g5en-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:20 +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 1AUG3atG031981; Tue, 30 Nov 2021 16:07:18 GMT Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by ppma01dal.us.ibm.com with ESMTP id 3ckcabr04j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:18 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7Cf951773740 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:13 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CD0B6B20A2; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B9958B20A6; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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: [RFC 14/20] ima: Move some IMA policy and filesystem related variables into ima_namespace Date: Tue, 30 Nov 2021 11:06:48 -0500 Message-Id: <20211130160654.1418231-15-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: nKDBdyUnZsQGgUiyi2ZIzlroqXSFMqtS X-Proofpoint-ORIG-GUID: KAByMAmFlQ1j7M9WRChdZqz1G507eRsR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 phishscore=0 spamscore=0 malwarescore=0 clxscore=1015 mlxlogscore=999 adultscore=0 mlxscore=0 bulkscore=0 impostorscore=0 priorityscore=1501 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 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 | 35 +++++++++++------------- security/integrity/ima/ima_init_ima_ns.c | 4 +++ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index 850a513834d2..fe08919df326 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -262,6 +262,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 c35e15fb313f..6c86f81c9998 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) { @@ -320,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; @@ -337,7 +334,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; @@ -350,14 +347,14 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, 1, 0); result = -EACCES; } else { - result = ima_parse_add_rule(get_current_ns(), data); + 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; } @@ -374,8 +371,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, @@ -390,6 +385,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; @@ -401,7 +398,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; } @@ -415,25 +412,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; } @@ -442,7 +439,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 57e46a10c001..22ff74e85a5f 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 Tue Nov 30 16:06:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647691 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 B9646C433EF for ; Tue, 30 Nov 2021 16:08:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243668AbhK3QLZ (ORCPT ); Tue, 30 Nov 2021 11:11:25 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:29540 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243452AbhK3QLA (ORCPT ); Tue, 30 Nov 2021 11:11:00 -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 1AUFlUc4001239; Tue, 30 Nov 2021 16:07:17 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 : content-transfer-encoding : mime-version; s=pp1; bh=lGwNHCJCYs+XuGS6svOUrR9B9L2FrXF0CRsXbHhmFHU=; b=lv1UoZ6o/nyL0wT25CDj9Rrjkx8bl7X1OzNZgaRJ8pHxfz04O33YarLqaPHU9E+oaf/o PyvnbnvIvjix+KeVW7N6P4Q6JviSOy5A+hWUdg220MqtLTI/aqDg6KrxkXECxaiT1tRr cxn98cAXgW6g3UZrHRMwdi6XIjCOPjUgRufcOBaSwjPhshxn6BTH1BQTQTVG7O+iW6Yd 87k7zBll2XiQhaflaKI39ronJ/HMO5U48uoganUmHRTFODBL7joUoN8e1si6Q6RFeP1T gH4H6Y2oIonq2u4ucAD4CMPGJEHYnl2gRV+HaECAnt4wWKdl9+xONiqLQ5TDkZmCN1g0 vw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpwm0gwf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +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 1AUFnhUf007457; Tue, 30 Nov 2021 16:07:16 GMT Received: from ppma03wdc.us.ibm.com (ba.79.3fa9.ip4.static.sl-reverse.com [169.63.121.186]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpwm0gv9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUG3dhW014046; Tue, 30 Nov 2021 16:07:15 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 3cn3k1qgtg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7Dp853084494 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:13 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0735BB2099; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D8758B2073; Tue, 30 Nov 2021 16:07:12 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:12 +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, Denis Semakin , Stefan Berger Subject: [RFC 15/20] capabilities: Introduce CAP_INTEGRITY_ADMIN Date: Tue, 30 Nov 2021 11:06:49 -0500 Message-Id: <20211130160654.1418231-16-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: a7hRstFw5cN4Jrq9GzLR9-QfelfNqLLx X-Proofpoint-GUID: JE_eh3-sQtu9kwX3hHFaojkO0LQXbXRH X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 malwarescore=0 mlxlogscore=999 spamscore=0 priorityscore=1501 lowpriorityscore=0 suspectscore=0 impostorscore=0 adultscore=0 bulkscore=0 clxscore=1015 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: From: Denis Semakin This patch introduces CAP_INTEGRITY_ADMIN, a new capability that allows to setup IMA (Integrity Measurement Architecture) policies per container for non-root users. The main purpose of this new capability is discribed in this document: https://kernsec.org/wiki/index.php/IMA_Namespacing_design_considerations It is said: "setting the policy should be possibly without the powerful CAP_SYS_ADMIN and there should be the opportunity to gate this with a new capability CAP_INTEGRITY_ADMIN that allows a user to set the IMA policy during container runtime.." In other words it should be possible to setup IMA policies while not giving too many privilges to the user, therefore splitting the CAP_INTEGRITY_ADMIN off from CAP_SYS_ADMIN. Signed-off-by: Denis Semakin Signed-off-by: Stefan Berger --- include/linux/capability.h | 6 ++++++ include/uapi/linux/capability.h | 7 ++++++- security/selinux/include/classmap.h | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 65efb74c3585..ea6d58acb95e 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -278,4 +278,10 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns, int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry, const void **ivalue, size_t size); +static inline bool integrity_admin_ns_capable(struct user_namespace *ns) +{ + return ns_capable(ns, CAP_INTEGRITY_ADMIN) || + ns_capable(ns, CAP_SYS_ADMIN); +} + #endif /* !_LINUX_CAPABILITY_H */ diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index 463d1ba2232a..48b08e4b3895 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h @@ -417,7 +417,12 @@ struct vfs_ns_cap_data { #define CAP_CHECKPOINT_RESTORE 40 -#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE +/* Allow setup IMA policy per container independently */ +/* No necessary to be superuser */ + +#define CAP_INTEGRITY_ADMIN 41 + +#define CAP_LAST_CAP CAP_INTEGRITY_ADMIN #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 35aac62a662e..7ff532b90f09 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -28,9 +28,9 @@ #define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \ "wake_alarm", "block_suspend", "audit_read", "perfmon", "bpf", \ - "checkpoint_restore" + "checkpoint_restore", "integrity_admin" -#if CAP_LAST_CAP > CAP_CHECKPOINT_RESTORE +#if CAP_LAST_CAP > CAP_INTEGRITY_ADMIN #error New capability defined, please update COMMON_CAP2_PERMS. #endif From patchwork Tue Nov 30 16:06:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647683 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 57277C4167B for ; Tue, 30 Nov 2021 16:08:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243614AbhK3QLS (ORCPT ); Tue, 30 Nov 2021 11:11:18 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:50674 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243430AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkT7N019624; Tue, 30 Nov 2021 16:07:19 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=MIVZzxjgMmeJCIdHNNw1iQwAyNiLWHTfl9Fay9tp2sE=; b=eZa1m56uK9ibsWII3iByxFLaq7op9RdiSYGZAvMooIdGy4HDBWrieIVZWmeyUIRxDjtZ k0flCmtioqacf2RykFQHVG6EUE6THjMp6lo/KUMFNq+K+AQgZW0hZ8Vdge5e6Y4p1gNF okFf6OlPeAPWOCtzZNkvrvuqGnFoFvFJwJAJRBAY5q26hV81NMsscuMxP5x8N3pphbaO /2NR4UduwnVyg0F9nlwR8w1AmphYLNdv3ph5mL4J3k+T6YFJSQh8FYVPaoTuJSaGCFSc yZruLvNBnmxN1tthYP4jOUofzEeUtM5nEp3yfqkec2b/eWW3OhhVSHgciy7tu29yWlYU ug== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghuw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFsvAP025794; Tue, 30 Nov 2021 16:07:16 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 3cnpw4ghu5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUG41NO003119; Tue, 30 Nov 2021 16:07:15 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 3ckcaayqvj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7DE862390686 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:13 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2B249B206B; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 11CF4B2066; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:13 +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: [RFC 16/20] ima: Use ns_capable() for namespace policy access Date: Tue, 30 Nov 2021 11:06:50 -0500 Message-Id: <20211130160654.1418231-17-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: yJvZb5TsMfaBc7dBUXcRxBz_sYaD6KaH X-Proofpoint-ORIG-GUID: AKdySvXM8bkdAToGzjx5LNn-ySfcQC_5 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Replace capable() with ns_capable() for IMA namespace policy access with the CAP_SYS_ADMIN permission. Signed-off-by: Stefan Berger --- security/integrity/ima/ima_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 6c86f81c9998..fd2798f2d224 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -393,7 +393,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 (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) return -EPERM; return seq_open(filp, &ima_policy_seqops); #endif From patchwork Tue Nov 30 16:06:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647675 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 A30BCC433F5 for ; Tue, 30 Nov 2021 16:07:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239087AbhK3QLM (ORCPT ); Tue, 30 Nov 2021 11:11:12 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:32234 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243387AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkTUG019631; Tue, 30 Nov 2021 16:07:19 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=HvSIr4/cE/ykM+BOl8ggkrbIKLz5U1uXYA78J57ufog=; b=NQVHtdu3D0Bd2RiDaNXboEk+ZgdAZ4q9k3CmSiYrYl8nsi8n9btCrXABASIi+SOZrEOb /rcUdNi7y1oyfZJT7c8mepu6GSbCv+jYUiOGpQsnsfwWhD+4g784trIxGTRHPr/1QBiD LRfsbEhSRm6Xnp3DtYlumuLGV71ChTO5NGW/ckUa/tnGKuaLyP1bHzZEUG+4bVZkezds yIar4cdPlFwUsoIjHO8xnugwoEKKlnfoBoZ3dmAURfUajeQ6saS82TXCkaUPLRaQWUrm nGWlWiv/Dm0HjG2CALMuHUGXKBjp9jNVIkkQR62rY2tLFnhLXC3mPx5v/xMM80PVpyZ0 9g== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghv3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFl0Br023444; Tue, 30 Nov 2021 16:07:16 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 3cnpw4ghud-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUG4NH5023605; Tue, 30 Nov 2021 16:07:15 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 3cn5ey2839-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7DFo18481582 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:13 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 506BDB209A; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 34878B2091; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:13 +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, Denis Semakin Subject: [RFC 17/20] ima: Use integrity_admin_ns_capable() to check corresponding capability Date: Tue, 30 Nov 2021 11:06:51 -0500 Message-Id: <20211130160654.1418231-18-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: s2aGokf7_edb40E58NOr039WG-427ibL X-Proofpoint-ORIG-GUID: bO9JnrnDA_K5u2L7k0F-whjc2HbLO096 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=831 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: From: Denis Semakin Use integrity_admin_ns_capable() to check corresponding capability to allow read/write IMA policy without CAP_SYS_ADMIN but with CAP_INTEGRITY_ADMIN. Signed-off-by: Denis Semakin --- security/integrity/ima/ima_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index fd2798f2d224..6766bb8262f2 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -393,7 +393,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp) #else if ((filp->f_flags & O_ACCMODE) != O_RDONLY) return -EACCES; - if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) + if (!integrity_admin_ns_capable(ns->user_ns)) return -EPERM; return seq_open(filp, &ima_policy_seqops); #endif From patchwork Tue Nov 30 16:06:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647687 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 9D7B8C433FE for ; Tue, 30 Nov 2021 16:08:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243627AbhK3QLT (ORCPT ); Tue, 30 Nov 2021 11:11:19 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:60678 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243424AbhK3QK7 (ORCPT ); Tue, 30 Nov 2021 11:10:59 -0500 Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1AUFkUiJ019688; Tue, 30 Nov 2021 16:07:19 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=Pek8epzdzpxEN+nG+RHo3egO/gaDeVYufYkeMvLUIRs=; b=QnelxNu4j35G5zTKjoag8QXMWVhSQ8WR1ew6AHd33oecF4e7fG3ZzyrCty7nqHC3j28Z tKoTLQJo/oUG+R/SwbIJCDcs8h6mFxFY6Xjv9p0KNLIqQ2qgKmYZ1TkDIWNoXd99Vx0C Oq2R4k8g/5Kxbljp5Y176uFaB7qJwdJyk0p57642h6pMOvPVw8SPlcYNcXjH/8S5dWj2 1PGxupV8/gIiV5LeMu7HwhNm0MJvI6iM7lJiauoy/OH4vbVLRl2CGySz7ufmZYiM7TdB O1sf6t2iWVuvX51BQqSQrQgKMPEf/IxCcp7W9GCSpbuo5WZ/aq4LfdYLNSegqMhgX3XS aQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpw4ghw6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:18 +0000 Received: from m0098396.ppops.net (m0098396.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1AUFkbhA020557; Tue, 30 Nov 2021 16:07:18 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 3cnpw4ghvf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:18 +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 1AUG2pjQ024657; Tue, 30 Nov 2021 16:07:17 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 3cnne1b9w2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7EHu59638096 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:14 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7CEF6B2091; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5C831B209D; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:13 +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: [RFC 18/20] userns: Introduce a refcount variable for calling early teardown function Date: Tue, 30 Nov 2021 11:06:52 -0500 Message-Id: <20211130160654.1418231-19-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: IdUt_42I6xN2R1XhEQtzjqW8TvUljqUf X-Proofpoint-ORIG-GUID: Oa9jrwP7tsZsJGTmELVq0ff96JbTOkYY X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 bulkscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1015 malwarescore=0 phishscore=0 adultscore=0 impostorscore=0 spamscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Extend the user_namespace structure with a refcount_teardown variable to cause an early teardown function to be invoked. This allows the IMA namespace to initialize a filesystem that holds one additional reference to the user namespace it 'belongs' to. Therefore, the refount_teardown variable will be incremented by '1' once that additional reference has been created. Once the user namespace's reference counter is decremented to '1', this early teardown function is invoked and the additional user namespace reference released and the actual deletion of the user namespace can then proceed as usual. Signed-off-by: Stefan Berger --- include/linux/user_namespace.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 5249db04d62b..505e3b3748b6 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -103,6 +103,11 @@ struct user_namespace { #ifdef CONFIG_IMA struct ima_namespace *ima_ns; #endif + /* The refcount at which to start tearing down dependent namespaces + * (currently only IMA) that may hold additional references to the + * user namespace. + */ + unsigned int refcount_teardown; } __randomize_layout; struct ucounts { @@ -156,8 +161,12 @@ extern void __put_user_ns(struct user_namespace *ns); static inline void put_user_ns(struct user_namespace *ns) { - if (ns && refcount_dec_and_test(&ns->ns.count)) - __put_user_ns(ns); + if (ns) { + if (refcount_dec_and_test(&ns->ns.count)) + __put_user_ns(ns); + else if (refcount_read(&ns->ns.count) == ns->refcount_teardown) + ; + } } struct seq_operations; From patchwork Tue Nov 30 16:06:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647701 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 64FFEC433FE for ; Tue, 30 Nov 2021 16:08:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238201AbhK3QLb (ORCPT ); Tue, 30 Nov 2021 11:11:31 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:14490 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243483AbhK3QLC (ORCPT ); Tue, 30 Nov 2021 11:11:02 -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 1AUFQDQA010483; Tue, 30 Nov 2021 16:07:18 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=pOKE3jw6FW1nbqXSMnOvb0qVChrphXK9yGRylQbzf1o=; b=rcJygH5K9F1B8CiunH9rfhrY6k83zU25NYua+zkhNjxOKG5I1RxjX42o516IxeX18V66 DzDuH7Fz5h7L2TKQ2fZ7704nZZ9RBDKv4ZRTfIB6VJ20fsJ3wEquD3CISjpLJOz/duaA 4ZehfQU2D4LSNj7eohp+YvfEFDbvR9BcW/wkGYqLtMbeBSfIfSZp8PWfOb2CbOpR/ZVu 5VbQclkxn1fyqdd9GBR7V+NkX13rCbE2P85dzG04wqopTYVWPh/0dLp0QFMvsGQmAXZI ZZIntKna53f/bON5tQqOTFmAwMtcyeXhFdu3BXOF7s4DdD/G84kVRYFQCRo0jwfY1B6Q zw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnphjs56e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:18 +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 1AUFWomQ007114; Tue, 30 Nov 2021 16:07:17 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 3cnphjs55c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:17 +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 1AUG4NYv023600; Tue, 30 Nov 2021 16:07:16 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 3cn5ey284d-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7EcG45482326 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:14 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A8431B20A9; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 86ABDB20A4; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:13 +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: [RFC 19/20] ima/userns: Define early teardown function for IMA namespace Date: Tue, 30 Nov 2021 11:06:53 -0500 Message-Id: <20211130160654.1418231-20-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 8r1ZOwdnP5ax1q4U2L1x7dJ4yLRf-Dc5 X-Proofpoint-ORIG-GUID: iFTy7kgl22Fhz3FoI5r_im2kwAfCdG1O X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 spamscore=0 priorityscore=1501 mlxscore=0 adultscore=0 mlxlogscore=999 malwarescore=0 suspectscore=0 lowpriorityscore=0 bulkscore=0 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Define an early teardown function ima_ns_userns_early_teardown() that will be needed for early teardown of the securityfs_ns of an IMA name- space since this holds one additional references to the user namespace. This function is not called yet since the refcount_teardown variable at this point is always 0. Signed-off-by: Stefan Berger --- include/linux/user_namespace.h | 8 ++++++-- security/integrity/ima/ima_ns.c | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 505e3b3748b6..6bc178d4c6e2 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -158,14 +158,18 @@ static inline struct user_namespace *get_user_ns(struct user_namespace *ns) extern int create_user_ns(struct cred *new); extern int unshare_userns(unsigned long unshare_flags, struct cred **new_cred); extern void __put_user_ns(struct user_namespace *ns); +extern void ima_ns_userns_early_teardown(struct ima_namespace *ima_ns); static inline void put_user_ns(struct user_namespace *ns) { if (ns) { if (refcount_dec_and_test(&ns->ns.count)) __put_user_ns(ns); - else if (refcount_read(&ns->ns.count) == ns->refcount_teardown) - ; + else if (refcount_read(&ns->ns.count) == ns->refcount_teardown) { +#ifdef CONFIG_IMA_NS + ima_ns_userns_early_teardown(ns->ima_ns); +#endif + } } } diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index e4f4cf84a6b5..e7ad52b79f99 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "ima.h" @@ -64,6 +65,11 @@ struct ima_namespace *copy_ima_ns(struct ima_namespace *old_ns, return create_ima_ns(user_ns); } +void ima_ns_userns_early_teardown(struct ima_namespace *ns) +{ +} +EXPORT_SYMBOL(ima_ns_userns_early_teardown); + static void destroy_ima_ns(struct ima_namespace *ns) { pr_debug("DESTROY ima_ns: 0x%p\n", ns); From patchwork Tue Nov 30 16:06:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12647663 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 9A7ECC433FE for ; Tue, 30 Nov 2021 16:07:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238039AbhK3QKi (ORCPT ); Tue, 30 Nov 2021 11:10:38 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:29354 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232416AbhK3QKh (ORCPT ); Tue, 30 Nov 2021 11:10:37 -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 1AUFqa0r016474; Tue, 30 Nov 2021 16:07:16 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=rO4xW9VBkBHxY3zLtka6KyWZdlXzfeiQ0hg5qgkdeV8=; b=Lgupuxv8ktUWLSuQTxcQCe9+VYzHj5QyT8eRyepbqvSdzzZvcIdmbVgz1u/ELz0e7MPr d2jFjuFVa5NnpyiRWvMVbhOrq/PDP41nXrwZ1fO45aCVduZNGYWmJ9gUv15gzQI67xCb hZN/b5gyHW/hybDimOay8wV9jx+YqbVhqdZz7sLJQKO5bbsj/tS3mU8mv40dyHaQKtuL 4WtwLbIY2cEA8rES2vAjlzz2tva14mIlksN4FeluCoN2xKdxa0aBEnRrJvyCVLlcg+Yv a7AseQKkQYLyApDBM4iFUwBQOyJBcBrvrRDSlnJ9tEJIrxTtpXZudGu3Zb9YyS9WWQrs 6Q== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3cnpyygb84-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:16 +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 1AUFtpN4025005; Tue, 30 Nov 2021 16:07:16 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 3cnpyygb7j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:15 +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 1AUG2j2D009847; Tue, 30 Nov 2021 16:07:14 GMT Received: from b01cxnp23033.gho.pok.ibm.com (b01cxnp23033.gho.pok.ibm.com [9.57.198.28]) by ppma02wdc.us.ibm.com with ESMTP id 3ckcab7tka-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 30 Nov 2021 16:07:14 +0000 Received: from b01ledav003.gho.pok.ibm.com (b01ledav003.gho.pok.ibm.com [9.57.199.108]) by b01cxnp23033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1AUG7EFN18285020 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 30 Nov 2021 16:07:14 GMT Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D0348B209F; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from b01ledav003.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B1EF4B20AC; Tue, 30 Nov 2021 16:07:13 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav003.gho.pok.ibm.com (Postfix) with ESMTP; Tue, 30 Nov 2021 16:07:13 +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: [RFC 20/20] ima: Setup securityfs_ns for IMA namespace Date: Tue, 30 Nov 2021 11:06:54 -0500 Message-Id: <20211130160654.1418231-21-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211130160654.1418231-1-stefanb@linux.ibm.com> References: <20211130160654.1418231-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: Oo7cAhv30aGK1GQOktjuac2vf1c93onh X-Proofpoint-GUID: _NyztsU0zZtWt3tfAKqv2cfNJkt02PwI X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-11-30_09,2021-11-28_01,2020-04-07_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 mlxscore=0 suspectscore=0 impostorscore=0 bulkscore=0 phishscore=0 adultscore=0 mlxlogscore=999 clxscore=1015 malwarescore=0 priorityscore=1501 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2111300084 Precedence: bulk List-ID: Setup securityfs_ns 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. Increment the user namespace's refcount_teardown value by '1' once securityfs_ns has been successfully setup since the initialization of the filesystem causes an additional reference to the user namespace to be taken. The early teardown function will delete the file system and release the additional reference. The securityfs_ns file and directory ownerships cannot be set when the filesystem is setup since at this point the user namespace has not been configured yet by the user and therefore the ownership mappings are not available, yet. Therefore, adjust the file and directory ownerships when an inode's function for determining the permissions of a file or directory is accessed. This filesystem can now be mounted as follows: mount -t securityfs_ns /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 nobody nobody 0 Nov 27 06:44 ima -> integrity/ima drwxr-xr-x. 3 nobody nobody 0 Nov 27 06:44 integrity $ ls -l sys/kernel/security/ima/ total 0 -r--r-----. 1 root root 0 Nov 27 06:44 ascii_runtime_measurements -r--r-----. 1 root root 0 Nov 27 06:44 binary_runtime_measurements -rw-------. 1 root root 0 Nov 27 06:44 policy -r--r-----. 1 root root 0 Nov 27 06:44 runtime_measurements_count -r--r-----. 1 root root 0 Nov 27 06:44 violations Signed-off-by: Stefan Berger --- include/linux/ima.h | 17 +++ security/integrity/ima/ima.h | 2 + security/integrity/ima/ima_fs.c | 178 ++++++++++++++++++++++- security/integrity/ima/ima_init_ima_ns.c | 6 +- security/integrity/ima/ima_ns.c | 4 +- 5 files changed, 203 insertions(+), 4 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index fe08919df326..a2c5e516f706 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -221,6 +221,18 @@ struct ima_h_table { struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE]; }; +enum { + IMAFS_DENTRY_INTEGRITY_DIR = 0, + IMAFS_DENTRY_DIR, + IMAFS_DENTRY_SYMLINK, + IMAFS_DENTRY_BINARY_RUNTIME_MEASUREMENTS, + IMAFS_DENTRY_ASCII_RUNTIME_MEASUREMENTS, + IMAFS_DENTRY_RUNTIME_MEASUREMENTS_COUNT, + IMAFS_DENTRY_VIOLATIONS, + IMAFS_DENTRY_IMA_POLICY, + IMAFS_DENTRY_LAST +}; + struct ima_namespace { struct kref kref; struct user_namespace *user_ns; @@ -267,6 +279,11 @@ struct ima_namespace { struct mutex ima_write_mutex; unsigned long ima_fs_flags; int valid_policy; + + struct dentry *dentry[IMAFS_DENTRY_LAST]; + struct vfsmount *mount; + int mount_count; + bool file_ownership_fixes_done; }; extern struct ima_namespace init_ima_ns; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index bb9763cd5fb1..9bcd71bb716c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -139,6 +139,8 @@ struct ns_status { /* Internal IMA function definitions */ int ima_init(void); int ima_fs_init(void); +int ima_fs_ns_init(struct ima_namespace *ns); +void ima_fs_ns_free(struct ima_namespace *ns); int ima_add_template_entry(struct ima_namespace *ns, struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 6766bb8262f2..9a14be520268 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "ima.h" @@ -436,8 +437,13 @@ 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; + if (ns == &init_ima_ns) { + securityfs_remove(ima_policy); + ima_policy = NULL; + } else { + securityfs_ns_remove(ns->dentry[IMAFS_DENTRY_POLICY]); + ns->dentry[IMAFS_DENTRY_POLICY] = NULL; + } #elif defined(CONFIG_IMA_WRITE_POLICY) clear_bit(IMA_FS_BUSY, &ns->ima_fs_flags); #elif defined(CONFIG_IMA_READ_POLICY) @@ -509,3 +515,171 @@ int __init ima_fs_init(void) securityfs_remove(ima_policy); return -1; } + +/* + * Fix the ownership (uid/gid) of the dentry's that couldn't be set at the + * time of their creation because the user namespace wasn't configured, yet. + */ +static void ima_fs_ns_fixup_uid_gid(struct ima_namespace *ns) +{ + struct inode *inode; + size_t i; + + if (ns->file_ownership_fixes_done || + ns->user_ns->uid_map.nr_extents == 0) + return; + + ns->file_ownership_fixes_done = true; + for (i = 0; i < IMAFS_DENTRY_LAST; i++) { + if (!ns->dentry[i]) + continue; + inode = ns->dentry[i]->d_inode; + inode->i_uid = make_kuid(ns->user_ns, 0); + inode->i_gid = make_kgid(ns->user_ns, 0); + } +} + +/* Fix the permissions when a file is opened */ +int ima_fs_ns_permission(struct user_namespace *mnt_userns, struct inode *inode, + int mask) +{ + ima_fs_ns_fixup_uid_gid(get_current_ns()); + return generic_permission(mnt_userns, inode, mask); +} + +const struct inode_operations ima_fs_ns_inode_operations = { + .lookup = simple_lookup, + .permission = ima_fs_ns_permission, +}; + +int ima_fs_ns_init(struct ima_namespace *ns) +{ + struct dentry *parent; + + ns->mount = securityfs_ns_create_mount(ns->user_ns); + if (IS_ERR(ns->mount)) { + ns->mount = NULL; + return -1; + } + ns->mount_count += 1; + + ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] = + securityfs_ns_create_dir("integrity", NULL, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR])) { + ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_DIR] = + securityfs_ns_create_dir("ima", ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR], + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_DIR])) { + ns->dentry[IMAFS_DENTRY_DIR] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_SYMLINK] = + securityfs_ns_create_symlink("ima", NULL, "integrity/ima", NULL, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_SYMLINK])) { + ns->dentry[IMAFS_DENTRY_SYMLINK] = NULL; + goto out; + } + + parent = ns->dentry[IMAFS_DENTRY_DIR]; + ns->dentry[IMAFS_DENTRY_BINARY_RUNTIME_MEASUREMENTS] = + securityfs_ns_create_file("binary_runtime_measurements", + S_IRUSR | S_IRGRP, parent, NULL, + &ima_measurements_ops, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_BINARY_RUNTIME_MEASUREMENTS])) { + ns->dentry[IMAFS_DENTRY_BINARY_RUNTIME_MEASUREMENTS] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_ASCII_RUNTIME_MEASUREMENTS] = + securityfs_ns_create_file("ascii_runtime_measurements", + S_IRUSR | S_IRGRP, parent, NULL, + &ima_ascii_measurements_ops, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_ASCII_RUNTIME_MEASUREMENTS])) { + ns->dentry[IMAFS_DENTRY_ASCII_RUNTIME_MEASUREMENTS] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_RUNTIME_MEASUREMENTS_COUNT] = + securityfs_ns_create_file("runtime_measurements_count", + S_IRUSR | S_IRGRP, parent, NULL, + &ima_measurements_count_ops, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_RUNTIME_MEASUREMENTS_COUNT])) { + ns->dentry[IMAFS_DENTRY_RUNTIME_MEASUREMENTS_COUNT] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_VIOLATIONS] = + securityfs_ns_create_file("violations", S_IRUSR | S_IRGRP, + parent, NULL, &ima_htable_violations_ops, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_VIOLATIONS])) { + ns->dentry[IMAFS_DENTRY_VIOLATIONS] = NULL; + goto out; + } + + ns->dentry[IMAFS_DENTRY_IMA_POLICY] = + securityfs_ns_create_file("policy", POLICY_FILE_FLAGS, + parent, NULL, + &ima_measure_policy_ops, + &ima_fs_ns_inode_operations, + &ns->mount, &ns->mount_count); + if (IS_ERR(ns->dentry[IMAFS_DENTRY_IMA_POLICY])) { + ns->dentry[IMAFS_DENTRY_IMA_POLICY] = NULL; + goto out; + } + + /* Adjust the trigger for user namespace's early teardown of dependent + * namespaces. Due to the filesystem there's an additional reference + * to the user namespace. + */ + ns->user_ns->refcount_teardown += 1; + + return 0; + +out: + ima_fs_ns_free(ns); + + return -1; +} + +void ima_fs_ns_free(struct ima_namespace *ns) +{ + size_t i; + + for (i = 0; i < IMAFS_DENTRY_LAST; i++) { + switch (i) { + case IMAFS_DENTRY_DIR: + case IMAFS_DENTRY_INTEGRITY_DIR: + /* files first */ + continue; + } + securityfs_ns_remove(ns->dentry[i], &ns->mount, &ns->mount_count); + ns->dentry[i] = NULL; + } + securityfs_ns_remove(ns->dentry[IMAFS_DENTRY_DIR], &ns->mount, &ns->mount_count); + ns->dentry[IMAFS_DENTRY_DIR] = NULL; + securityfs_ns_remove(ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR], &ns->mount, &ns->mount_count); + ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] = NULL; + + if (ns->mount) { + mntput(ns->mount); + ns->mount_count -= 1; + } + ns->mount = NULL; +} diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c index 22ff74e85a5f..86a89502c0c5 100644 --- a/security/integrity/ima/ima_init_ima_ns.c +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -20,6 +20,8 @@ int ima_init_namespace(struct ima_namespace *ns) { + int rc = 0; + ns->ns_status_tree = RB_ROOT; rwlock_init(&ns->ns_status_lock); ns->ns_status_cache = KMEM_CACHE(ns_status, SLAB_PANIC); @@ -52,8 +54,10 @@ int ima_init_namespace(struct ima_namespace *ns) mutex_init(&ns->ima_write_mutex); ns->valid_policy = 1; ns->ima_fs_flags = 0; + if (ns != &init_ima_ns) + rc = ima_fs_ns_init(ns); - return 0; + return rc; } int __init ima_ns_init(void) diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index e7ad52b79f99..c687e840441a 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -67,7 +67,9 @@ struct ima_namespace *copy_ima_ns(struct ima_namespace *old_ns, void ima_ns_userns_early_teardown(struct ima_namespace *ns) { -} + pr_debug("%s: ns=0x%lx\n", __func__, (unsigned long)ns); + ima_fs_ns_free(ns); +}; EXPORT_SYMBOL(ima_ns_userns_early_teardown); static void destroy_ima_ns(struct ima_namespace *ns)