From patchwork Fri Dec 10 19:47:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Berger X-Patchwork-Id: 12670845 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E079DC433EF for ; Fri, 10 Dec 2021 19:48:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343761AbhLJTvi (ORCPT ); Fri, 10 Dec 2021 14:51:38 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:56842 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1343713AbhLJTv3 (ORCPT ); Fri, 10 Dec 2021 14:51:29 -0500 Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJRwi2021289; Fri, 10 Dec 2021 19:47:41 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=ByNF7ROf2DqzpRSnI/OPFdOK/GBjbR3Rry0Bm2YyfS4=; b=c664Y2CHdDoyHf6ppnbk83Rotzf9GE+qGh5AuMSVZDYNphETDwn9rlfd5z/tCSJ7GwrC dEW9ytGtEW0M5BRf9GO9vreHwHR2hED6eU+4KkzNcD47ss5S6oB757vrNEknuMD35DNw HgZnPr6bDm3e3IDCiLK4x/kSiwIdjuo0daDNNRzeTcwcc2z2Qz1XCHhJ6A3XIzJE3Haa r8zD3thAIVq67IAMwY3mjp3OjO/jI2+aGy6+yceBN5JDjiBIJ3hestiKo1N2lYE4/V3Y xxvhXXoLlwV+w0ZNpSYb1H+DB2Zg3WBYNiGBNYRdFByhkOR0j84M86CZt5Imhnoh3rFl tA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2u8b85-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from m0098416.ppops.net (m0098416.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 1BAJS8g4022468; Fri, 10 Dec 2021 19:47:40 GMT Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0b-001b2d01.pphosted.com with ESMTP id 3cvd2u8b7u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:40 +0000 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 1BAJc5OU011559; Fri, 10 Dec 2021 19:47:39 GMT Received: from b01cxnp23034.gho.pok.ibm.com (b01cxnp23034.gho.pok.ibm.com [9.57.198.29]) by ppma01dal.us.ibm.com with ESMTP id 3cqyyekvye-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 10 Dec 2021 19:47:39 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 1BAJlc0L38207860 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 10 Dec 2021 19:47:38 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EE56BAE05F; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CE5E8AE064; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) Received: from sbct-3.pok.ibm.com (unknown [9.47.158.153]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Fri, 10 Dec 2021 19:47:37 +0000 (GMT) From: Stefan Berger To: linux-integrity@vger.kernel.org Cc: zohar@linux.ibm.com, serge@hallyn.com, christian.brauner@ubuntu.com, containers@lists.linux.dev, dmitry.kasatkin@gmail.com, ebiederm@xmission.com, krzysztof.struczynski@huawei.com, roberto.sassu@huawei.com, mpeters@redhat.com, lhinds@redhat.com, lsturman@redhat.com, puiterwi@redhat.com, jejb@linux.ibm.com, jamjoom@us.ibm.com, linux-kernel@vger.kernel.org, paul@paul-moore.com, rgb@redhat.com, linux-security-module@vger.kernel.org, jmorris@namei.org, Stefan Berger , James Bottomley Subject: [PATCH v6 01/17] ima: Add IMA namespace support Date: Fri, 10 Dec 2021 14:47:20 -0500 Message-Id: <20211210194736.1538863-2-stefanb@linux.ibm.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211210194736.1538863-1-stefanb@linux.ibm.com> References: <20211210194736.1538863-1-stefanb@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: mylM2eX3m8H-pdfm51JFN-7h2fg12FKM X-Proofpoint-ORIG-GUID: IlFnzNf_-76I3AlAvrKPlkDfYYimp3XU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2021-12-10_07,2021-12-10_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 suspectscore=0 phishscore=0 priorityscore=1501 spamscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 impostorscore=0 mlxlogscore=999 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2112100106 Precedence: bulk List-ID: Implement an IMA namespace data structure that gets created alongside a user namespace with CLONE_NEWUSER. This lays down the foundation for namespacing the different aspects of IMA (eg. IMA-audit, IMA-measurement, IMA-appraisal). Signed-off-by: Stefan Berger Suggested-by: James Bottomley --- include/linux/ima.h | 37 +++++++++++++ include/linux/user_namespace.h | 4 ++ init/Kconfig | 10 ++++ kernel/user.c | 7 +++ kernel/user_namespace.c | 8 +++ security/integrity/ima/Makefile | 3 +- security/integrity/ima/ima.h | 4 ++ security/integrity/ima/ima_init.c | 4 ++ security/integrity/ima/ima_init_ima_ns.c | 32 +++++++++++ security/integrity/ima/ima_ns.c | 69 ++++++++++++++++++++++++ 10 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 security/integrity/ima/ima_init_ima_ns.c create mode 100644 security/integrity/ima/ima_ns.c diff --git a/include/linux/ima.h b/include/linux/ima.h index b6ab66a546ae..f282e40c316c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -11,6 +11,7 @@ #include #include #include +#include #include struct linux_binprm; @@ -210,6 +211,42 @@ static inline int ima_inode_removexattr(struct dentry *dentry, } #endif /* CONFIG_IMA_APPRAISE */ +struct ima_namespace { + int avoid_zero_size; +}; + +extern struct ima_namespace init_ima_ns; + +#ifdef CONFIG_IMA_NS + +void free_ima_ns(struct user_namespace *ns); +int create_ima_ns(struct user_namespace *user_ns); + +static inline struct ima_namespace *get_current_ns(void) +{ + return current_user_ns()->ima_ns; +} + +#else + +static inline void free_ima_ns(struct user_namespace *user_ns) +{ +} + +static inline int create_ima_ns(struct user_namespace *user_ns) +{ +#ifdef CONFIG_IMA + user_ns->ima_ns = &init_ima_ns; +#endif + return 0; +} + +static inline struct ima_namespace *get_current_ns(void) +{ + return &init_ima_ns; +} +#endif /* CONFIG_IMA_NS */ + #if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING) extern bool ima_appraise_signature(enum kernel_read_file_id func); #else diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 33a4240e6a6f..5249db04d62b 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -36,6 +36,7 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */ #define USERNS_INIT_FLAGS USERNS_SETGROUPS_ALLOWED struct ucounts; +struct ima_namespace; enum ucount_type { UCOUNT_USER_NAMESPACES, @@ -99,6 +100,9 @@ struct user_namespace { #endif struct ucounts *ucounts; long ucount_max[UCOUNT_COUNTS]; +#ifdef CONFIG_IMA + struct ima_namespace *ima_ns; +#endif } __randomize_layout; struct ucounts { diff --git a/init/Kconfig b/init/Kconfig index 11f8a845f259..27890607e8cb 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1242,6 +1242,16 @@ config NET_NS Allow user space to create what appear to be multiple instances of the network stack. +config IMA_NS + bool "IMA namespace" + depends on USER_NS + depends on IMA + default y + help + Allow the creation of IMA namespaces for each user namespace. + Namespaced IMA enables having IMA features work separately + in each IMA namespace. + endif # NAMESPACES config CHECKPOINT_RESTORE diff --git a/kernel/user.c b/kernel/user.c index e2cf8c22b539..287751d89b44 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -20,6 +20,10 @@ #include #include +#ifdef CONFIG_IMA +extern struct ima_namespace init_ima_ns; +#endif + /* * userns count is 1 for root user, 1 for init_uts_ns, * and 1 for... ? @@ -67,6 +71,9 @@ struct user_namespace init_user_ns = { .keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list), .keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem), #endif +#ifdef CONFIG_IMA + .ima_ns = &init_ima_ns, +#endif }; EXPORT_SYMBOL_GPL(init_user_ns); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 6b2e3ca7ee99..6fa01323aac9 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -20,6 +20,7 @@ #include #include #include +#include static struct kmem_cache *user_ns_cachep __read_mostly; static DEFINE_MUTEX(userns_state_mutex); @@ -141,8 +142,14 @@ int create_user_ns(struct cred *new) if (!setup_userns_sysctls(ns)) goto fail_keyring; + ret = create_ima_ns(ns); + if (ret) + goto fail_sysctls; + set_cred_user_ns(new, ns); return 0; +fail_sysctls: + retire_userns_sysctls(ns); fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS key_put(ns->persistent_keyring_register); @@ -196,6 +203,7 @@ static void free_user_ns(struct work_struct *work) kfree(ns->projid_map.forward); kfree(ns->projid_map.reverse); } + free_ima_ns(ns); retire_userns_sysctls(ns); key_free_user_ns(ns); ns_free_inum(&ns->ns); diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 2499f2485c04..b86a35fbed60 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -7,13 +7,14 @@ obj-$(CONFIG_IMA) += ima.o ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ - ima_policy.o ima_template.o ima_template_lib.o + ima_policy.o ima_template.o ima_template_lib.o ima_init_ima_ns.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o +ima-$(CONFIG_IMA_NS) += ima_ns.o ifeq ($(CONFIG_EFI),y) ima-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_efi.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index be965a8715e4..2f8adf383054 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -418,6 +418,10 @@ static inline void ima_free_modsig(struct modsig *modsig) } #endif /* CONFIG_IMA_APPRAISE_MODSIG */ +int ima_ns_init(void); +struct ima_namespace; +int ima_init_namespace(struct ima_namespace *ns); + /* LSM based policy rules require audit */ #ifdef CONFIG_IMA_LSM_RULES diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index b26fa67476b4..f6ae4557a0da 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -120,6 +120,10 @@ int __init ima_init(void) { int rc; + rc = ima_ns_init(); + if (rc) + return rc; + ima_tpm_chip = tpm_default_chip(); if (!ima_tpm_chip) pr_info("No TPM chip found, activating TPM-bypass!\n"); diff --git a/security/integrity/ima/ima_init_ima_ns.c b/security/integrity/ima/ima_init_ima_ns.c new file mode 100644 index 000000000000..f820686baf9f --- /dev/null +++ b/security/integrity/ima/ima_init_ima_ns.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun + * Stefan Berger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include +#include +#include +#include + +#include "ima.h" + +int ima_init_namespace(struct ima_namespace *ns) +{ + return 0; +} + +int __init ima_ns_init(void) +{ + return ima_init_namespace(&init_ima_ns); +} + +struct ima_namespace init_ima_ns = { +}; +EXPORT_SYMBOL(init_ima_ns); diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c new file mode 100644 index 000000000000..c575ddf0c3f3 --- /dev/null +++ b/security/integrity/ima/ima_ns.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2016-2021 IBM Corporation + * Author: + * Yuqiong Sun + * Stefan Berger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "ima.h" + +static struct kmem_cache *imans_cachep; + +int create_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns; + int err; + + ns = kmem_cache_zalloc(imans_cachep, GFP_KERNEL); + if (!ns) + return -ENOMEM; + pr_debug("NEW ima_ns: 0x%p\n", ns); + + err = ima_init_namespace(ns); + if (err) + goto fail_free; + + user_ns->ima_ns = ns; + + return 0; + +fail_free: + kmem_cache_free(imans_cachep, ns); + + return err; +} + +static void destroy_ima_ns(struct ima_namespace *ns) +{ + pr_debug("DESTROY ima_ns: 0x%p\n", ns); + kmem_cache_free(imans_cachep, ns); +} + +void free_ima_ns(struct user_namespace *user_ns) +{ + struct ima_namespace *ns = user_ns->ima_ns; + + if (WARN_ON(ns == &init_ima_ns)) + return; + + destroy_ima_ns(ns); +} + +static int __init imans_cache_init(void) +{ + imans_cachep = KMEM_CACHE(ima_namespace, SLAB_PANIC); + return 0; +} +subsys_initcall(imans_cache_init)