From patchwork Thu Sep 30 11:55:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528101 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DFC7C43217 for ; Thu, 30 Sep 2021 11:55:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4903A61A04 for ; Thu, 30 Sep 2021 11:55:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350594AbhI3L5a (ORCPT ); Thu, 30 Sep 2021 07:57:30 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3895 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350549AbhI3L53 (ORCPT ); Thu, 30 Sep 2021 07:57:29 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.201]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs7R6v0Bz67Yp1; Thu, 30 Sep 2021 19:52:51 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:55:45 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 1/7] integrity: Change type of IMA rule-related flags to u64 Date: Thu, 30 Sep 2021 13:55:27 +0200 Message-ID: <20210930115533.878169-2-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Change the type of the flags member of integrity_iint_cache and ima_rule_entry, and the type of return value of ima_match_policy() and ima_get_action() to u64 to make room for more flags. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 4 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_main.c | 3 +- security/integrity/ima/ima_policy.c | 6 +-- security/integrity/integrity.h | 60 ++++++++++++++--------------- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index d01ca3566aec..cde2e1c2a6be 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -255,7 +255,7 @@ static inline void ima_process_queued_keys(void) {} #endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */ /* LIM API function definitions */ -int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode, +u64 ima_get_action(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, @@ -286,7 +286,7 @@ 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, +u64 ima_match_policy(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, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 2c6c3a5228b5..bd9316d89243 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -185,7 +185,7 @@ 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, +u64 ima_get_action(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, diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index d33765c7aaa7..fe1f4ef1bb9d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -208,7 +208,8 @@ static int process_measurement(struct file *file, const struct cred *cred, char *pathbuf = NULL; char filename[NAME_MAX]; const char *pathname = NULL; - int rc = 0, action, must_appraise = 0; + u64 action; + int rc = 0, must_appraise = 0; int pcr = CONFIG_IMA_MEASURE_PCR_IDX; struct evm_ima_xattr_data *xattr_value = NULL; struct modsig *modsig = NULL; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8d6f5d85dfa4..084b5d9257da 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -74,7 +74,7 @@ struct ima_rule_opt_list { struct ima_rule_entry { struct list_head list; int action; - unsigned int flags; + u64 flags; enum ima_hooks func; int mask; unsigned long fsmagic; @@ -702,14 +702,14 @@ 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, +u64 ima_match_policy(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) { struct ima_rule_entry *entry; - int action = 0, actmask = flags | (flags << 1); + u64 action = 0, actmask = flags | (flags << 1); struct list_head *ima_rules_tmp; if (template_desc && !*template_desc) diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 2ab85f286d17..cb4a8cd2a213 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -23,27 +23,27 @@ #include /* iint action cache flags */ -#define IMA_MEASURE 0x00000001 -#define IMA_MEASURED 0x00000002 -#define IMA_APPRAISE 0x00000004 -#define IMA_APPRAISED 0x00000008 -/*#define IMA_COLLECT 0x00000010 do not use this flag */ -#define IMA_COLLECTED 0x00000020 -#define IMA_AUDIT 0x00000040 -#define IMA_AUDITED 0x00000080 -#define IMA_HASH 0x00000100 -#define IMA_HASHED 0x00000200 +#define IMA_MEASURE 0x0000000000000001 +#define IMA_MEASURED 0x0000000000000002 +#define IMA_APPRAISE 0x0000000000000004 +#define IMA_APPRAISED 0x0000000000000008 +/*#define IMA_COLLECT 0x0000000000000010 do not use this flag */ +#define IMA_COLLECTED 0x0000000000000020 +#define IMA_AUDIT 0x0000000000000040 +#define IMA_AUDITED 0x0000000000000080 +#define IMA_HASH 0x0000000000000100 +#define IMA_HASHED 0x0000000000000200 /* iint cache flags */ -#define IMA_ACTION_FLAGS 0xff000000 -#define IMA_DIGSIG_REQUIRED 0x01000000 -#define IMA_PERMIT_DIRECTIO 0x02000000 -#define IMA_NEW_FILE 0x04000000 -#define EVM_IMMUTABLE_DIGSIG 0x08000000 -#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 -#define IMA_MODSIG_ALLOWED 0x20000000 -#define IMA_CHECK_BLACKLIST 0x40000000 -#define IMA_META_IMMUTABLE_REQUIRED 0x80000000 +#define IMA_ACTION_FLAGS 0xffffffffff000000 +#define IMA_DIGSIG_REQUIRED 0x0000000001000000 +#define IMA_PERMIT_DIRECTIO 0x0000000002000000 +#define IMA_NEW_FILE 0x0000000004000000 +#define EVM_IMMUTABLE_DIGSIG 0x0000000008000000 +#define IMA_FAIL_UNVERIFIABLE_SIGS 0x0000000010000000 +#define IMA_MODSIG_ALLOWED 0x0000000020000000 +#define IMA_CHECK_BLACKLIST 0x0000000040000000 +#define IMA_META_IMMUTABLE_REQUIRED 0x0000000080000000 #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ IMA_HASH | IMA_APPRAISE_SUBMASK) @@ -52,16 +52,16 @@ IMA_APPRAISED_SUBMASK) /* iint subaction appraise cache flags */ -#define IMA_FILE_APPRAISE 0x00001000 -#define IMA_FILE_APPRAISED 0x00002000 -#define IMA_MMAP_APPRAISE 0x00004000 -#define IMA_MMAP_APPRAISED 0x00008000 -#define IMA_BPRM_APPRAISE 0x00010000 -#define IMA_BPRM_APPRAISED 0x00020000 -#define IMA_READ_APPRAISE 0x00040000 -#define IMA_READ_APPRAISED 0x00080000 -#define IMA_CREDS_APPRAISE 0x00100000 -#define IMA_CREDS_APPRAISED 0x00200000 +#define IMA_FILE_APPRAISE 0x0000000000001000 +#define IMA_FILE_APPRAISED 0x0000000000002000 +#define IMA_MMAP_APPRAISE 0x0000000000004000 +#define IMA_MMAP_APPRAISED 0x0000000000008000 +#define IMA_BPRM_APPRAISE 0x0000000000010000 +#define IMA_BPRM_APPRAISED 0x0000000000020000 +#define IMA_READ_APPRAISE 0x0000000000040000 +#define IMA_READ_APPRAISED 0x0000000000080000 +#define IMA_CREDS_APPRAISE 0x0000000000100000 +#define IMA_CREDS_APPRAISED 0x0000000000200000 #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ IMA_BPRM_APPRAISE | IMA_READ_APPRAISE | \ IMA_CREDS_APPRAISE) @@ -133,7 +133,7 @@ struct integrity_iint_cache { struct mutex mutex; /* protects: version, flags, digest */ struct inode *inode; /* back pointer to inode in question */ u64 version; /* track inode changes */ - unsigned long flags; + u64 flags; unsigned long measured_pcrs; unsigned long atomic_flags; enum integrity_status ima_file_status:4; From patchwork Thu Sep 30 11:55:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528103 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 779F5C433F5 for ; Thu, 30 Sep 2021 11:55:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 58DA561A03 for ; Thu, 30 Sep 2021 11:55:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350625AbhI3L5b (ORCPT ); Thu, 30 Sep 2021 07:57:31 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3896 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350553AbhI3L5a (ORCPT ); Thu, 30 Sep 2021 07:57:30 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.201]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs7n662Yz686cr; Thu, 30 Sep 2021 19:53:09 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:55:45 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 2/7] ima: Introduce new policy keyword use_diglim Date: Thu, 30 Sep 2021 13:55:28 +0200 Message-ID: <20210930115533.878169-3-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Introduce the 'use_diglim' policy keyword to enable the usage of DIGLIM if the file matches the other criteria of the rule. If the file or metadata digest is found in the DIGLIM hash table, 'use_diglim': - skips the creation of a new measurement entry (action=measure) - allows access to the file (action=appraise) Signed-off-by: Roberto Sassu --- Documentation/ABI/testing/ima_policy | 4 +++- security/integrity/ima/ima_policy.c | 36 +++++++++++++++++++++++++--- security/integrity/integrity.h | 2 ++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index a8a5791db14c..4979fc068b0e 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -27,7 +27,7 @@ Description: lsm: [[subj_user=] [subj_role=] [subj_type=] [obj_user=] [obj_role=] [obj_type=]] option: [[appraise_type=]] [template=] [permit_directio] - [appraise_flag=] [appraise_algos=] [keyrings=] + [appraise_flag=] [appraise_algos=] [keyrings=] [use_diglim] base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] @@ -60,6 +60,8 @@ Description: For example, "sha256,sha512" to only accept to appraise files where the security.ima xattr was hashed with one of these two algorithms. + use_diglim: enables usage of DIGLIM for measurement and + appraisal default policy: # PROC_SUPER_MAGIC diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 084b5d9257da..dfab21aeb7e1 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1048,7 +1048,7 @@ enum { Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos, Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings, - Opt_label, Opt_err + Opt_label, Opt_use_diglim, Opt_err }; static const match_table_t policy_tokens = { @@ -1087,6 +1087,7 @@ static const match_table_t policy_tokens = { {Opt_template, "template=%s"}, {Opt_keyrings, "keyrings=%s"}, {Opt_label, "label=%s"}, + {Opt_use_diglim, "use_diglim"}, {Opt_err, NULL} }; @@ -1181,6 +1182,15 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) if (entry->action != MEASURE && entry->flags & IMA_PCR) return false; + /* + * Ensure that measurements made with DIGLIM don't have the standard + * IMA PCR. + */ + if ((entry->flags & IMA_USE_DIGLIM_MEASURE) && + (!(entry->flags & IMA_PCR) || + entry->pcr == CONFIG_IMA_MEASURE_PCR_IDX)) + return false; + if (entry->action != APPRAISE && entry->flags & (IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS | @@ -1215,7 +1225,9 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) IMA_INMASK | IMA_EUID | IMA_PCR | IMA_FSNAME | IMA_DIGSIG_REQUIRED | IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS | - IMA_META_IMMUTABLE_REQUIRED)) + IMA_META_IMMUTABLE_REQUIRED | + IMA_USE_DIGLIM_MEASURE | + IMA_USE_DIGLIM_APPRAISE)) return false; break; @@ -1229,7 +1241,9 @@ static bool ima_validate_rule(struct ima_rule_entry *entry) IMA_FSNAME | IMA_DIGSIG_REQUIRED | IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED | IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS | - IMA_META_IMMUTABLE_REQUIRED)) + IMA_META_IMMUTABLE_REQUIRED | + IMA_USE_DIGLIM_MEASURE | + IMA_USE_DIGLIM_APPRAISE)) return false; break; @@ -1719,6 +1733,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) &(template_desc->num_fields)); entry->template = template_desc; break; + case Opt_use_diglim: + ima_log_string(ab, "use_diglim", args[0].from); + if (entry->action != IMA_MEASURE && + entry->action != IMA_APPRAISE) { + result = -EINVAL; + break; + } + + if (entry->action == IMA_MEASURE) + entry->flags |= IMA_USE_DIGLIM_MEASURE; + else + entry->flags |= IMA_USE_DIGLIM_APPRAISE; + break; case Opt_err: ima_log_string(ab, "UNKNOWN", p); result = -EINVAL; @@ -2058,6 +2085,9 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, "appraise_type=meta_immutable "); if (entry->flags & IMA_PERMIT_DIRECTIO) seq_puts(m, "permit_directio "); + if ((entry->flags & IMA_USE_DIGLIM_MEASURE) || + (entry->flags & IMA_USE_DIGLIM_APPRAISE)) + seq_puts(m, "use_diglim "); rcu_read_unlock(); seq_puts(m, "\n"); return 0; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index cb4a8cd2a213..89ed87a957bc 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -44,6 +44,8 @@ #define IMA_MODSIG_ALLOWED 0x0000000020000000 #define IMA_CHECK_BLACKLIST 0x0000000040000000 #define IMA_META_IMMUTABLE_REQUIRED 0x0000000080000000 +#define IMA_USE_DIGLIM_MEASURE 0x0000000100000000 +#define IMA_USE_DIGLIM_APPRAISE 0x0000000200000000 #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ IMA_HASH | IMA_APPRAISE_SUBMASK) From patchwork Thu Sep 30 11:55:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528107 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9157FC4167E for ; Thu, 30 Sep 2021 11:55:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7E0DE619EC for ; Thu, 30 Sep 2021 11:55:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350641AbhI3L5d (ORCPT ); Thu, 30 Sep 2021 07:57:33 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3897 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350576AbhI3L5a (ORCPT ); Thu, 30 Sep 2021 07:57:30 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs773cbdz67t01; Thu, 30 Sep 2021 19:52:35 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:55:46 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 3/7] ima: Introduce diglim and appraise_diglim policies Date: Thu, 30 Sep 2021 13:55:29 +0200 Message-ID: <20210930115533.878169-4-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Introduce two new hardcoded policies, 'diglim' and 'appraise_diglim' to measure and appraise digest lists and related files. In particular, the 'diglim' policy adds the new rule: measure func=DIGEST_LIST_CHECK pcr= use_diglim where PCR value is 11 or the one chosen with the ima_diglim_pcr= kernel option. It also adds the use_diglim directive to existing selected rules with hooks BPRM_CHECK, CREDS_CHECK, MMAP_CHECK, FILE_CHECK, MODULE_CHECK, FIRMWARE_CHECK and DIGEST_LIST_CHECK. A rule with the DIGEST_LIST_CHECK hook is sufficient to cover all aspects of the digest list loading process. For direct upload, the kernel reads the file with type READING_DIGEST_LIST, which is mapped to that hook. For upload by a user space parser, DIGLIM LSM performs a second read for every file opened by the parser (including the executable), also with type READING_DIGEST_LIST. The 'appraise_diglim' policy adds the new rule: appraise func=DIGEST_LIST_CHECK appraise_type=imasig|modsig use_diglim and, like for the 'diglim' policy, adds the use_diglim directive for the selected IMA rules with action appraise. Signed-off-by: Roberto Sassu --- .../admin-guide/kernel-parameters.txt | 19 +++- security/integrity/ima/ima_policy.c | 102 +++++++++++++++++- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index e0db162ba202..fa4959a321d8 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1835,6 +1835,13 @@ Use the canonical format for the binary runtime measurements, instead of host native format. + ima_diglim_pcr= + [IMA] + Format: 0 - 23 + default: 11 + Define the PCR to be used for measurement entries + created with the diglim IMA policy. + ima_hash= [IMA] Format: { md5 | sha1 | rmd160 | sha256 | sha384 | sha512 | ... } @@ -1846,7 +1853,8 @@ ima_policy= [IMA] The builtin policies to load during IMA setup. Format: "tcb | appraise_tcb | secure_boot | - fail_securely | critical_data" + fail_securely | critical_data | diglim | + appraise_diglim" The "tcb" policy measures all programs exec'd, files mmap'd for exec, and all files opened with the read @@ -1860,6 +1868,11 @@ the tmpfs filesystem, for the "ima_tcb", "tcb" and "exec_tcb" policies. + The "diglim" policy enables measurement of + DIGLIM-related files (e.g. digest lists, parsers) and + usage of DIGLIM for measurement (exec, mmap, open, + firmware and module loading). + The "appraise_tcb" policy appraises the integrity of all files owned by root. @@ -1876,6 +1889,10 @@ rule for the tmpfs and ramfs filesystems for the "appraise_tcb" and "appraise_exec_tcb" policies. + The "appraise_diglim" policy enables appraisal of + DIGLIM-related files and usage of DIGLIM for appraisal + (exec, mmap, open, firmware and module loading). + The "secure_boot" policy appraises the integrity of files (eg. kexec kernel image, kernel modules, firmware, policy, etc) based on file signatures. diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index dfab21aeb7e1..5e1532abca5d 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -162,6 +162,10 @@ static struct ima_rule_entry default_measurement_rules[] __ro_after_init = { {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC}, }; +static struct ima_rule_entry diglim_measure_rule __ro_after_init = { + .action = MEASURE, .func = DIGEST_LIST_CHECK, .flags = IMA_FUNC +}; + static struct ima_rule_entry default_appraise_rules[] __ro_after_init = { {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, @@ -228,6 +232,11 @@ static struct ima_rule_entry secure_boot_rules[] __ro_after_init = { .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, }; +static struct ima_rule_entry diglim_appraise_rule __ro_after_init = { + .action = APPRAISE, .func = DIGEST_LIST_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED +}; + static struct ima_rule_entry critical_data_rules[] __ro_after_init = { {.action = MEASURE, .func = CRITICAL_DATA, .flags = IMA_FUNC}, }; @@ -253,9 +262,12 @@ static int __init default_measure_policy_setup(char *str) __setup("ima_tcb", default_measure_policy_setup); static unsigned int ima_measure_skip_flags __initdata; +static unsigned int ima_measure_diglim __initdata; static unsigned int ima_appraise_skip_flags __initdata; +static unsigned int ima_diglim_pcr __initdata = 11; static bool ima_use_appraise_tcb __initdata; static bool ima_use_appraise_exec_immutable __initdata; +static bool ima_use_appraise_diglim __initdata; static bool ima_use_secure_boot __initdata; static bool ima_use_critical_data __initdata; static bool ima_fail_unverifiable_sigs __ro_after_init; @@ -273,7 +285,9 @@ static int __init policy_setup(char *str) else if ((strcmp(p, "exec_tcb") == 0) && !ima_policy) { ima_policy = DEFAULT_TCB; ima_measure_skip_flags |= IMA_SKIP_OPEN; - } else if (strcmp(p, "appraise_tcb") == 0) + } else if (strcmp(p, "diglim") == 0) + ima_measure_diglim = true; + else if (strcmp(p, "appraise_tcb") == 0) ima_use_appraise_tcb = true; else if ((strcmp(p, "appraise_tmpfs") == 0)) ima_appraise_skip_flags |= IMA_SKIP_TMPFS; @@ -282,6 +296,8 @@ static int __init policy_setup(char *str) ima_appraise_skip_flags |= IMA_SKIP_OPEN; } else if (strcmp(p, "appraise_exec_immutable") == 0) ima_use_appraise_exec_immutable = true; + else if (strcmp(p, "appraise_diglim") == 0) + ima_use_appraise_diglim = true; else if (strcmp(p, "secure_boot") == 0) ima_use_secure_boot = true; else if (strcmp(p, "critical_data") == 0) @@ -303,6 +319,28 @@ static int __init default_appraise_policy_setup(char *str) } __setup("ima_appraise_tcb", default_appraise_policy_setup); +static int __init default_diglim_pcr_setup(char *str) +{ + unsigned int pcr; + int ret; + + ret = kstrtouint(str, 10, &pcr); + if (ret < 0 || pcr > 23) { + pr_err("Invalid value for ima_diglim_pcr=\n"); + return 1; + } + + /* Using the default IMA PCR is forbidden. */ + if (ret == CONFIG_IMA_MEASURE_PCR_IDX) { + pr_err("Default IMA PCR cannot be used for ima_diglim_pcr=\n"); + return 1; + } + + ima_diglim_pcr = pcr; + return 1; +} +__setup("ima_diglim_pcr=", default_diglim_pcr_setup); + static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src) { struct ima_rule_opt_list *opt_list; @@ -812,6 +850,61 @@ void ima_update_policy_flags(void) ima_policy_flag = new_policy_flag; } +/* + * Add the IMA_USE_DIGLIM_MEASURE and IMA_USE_DIGLIM_APPRAISE flags to the + * initial policy depending on the options in the kernel command line, and set + * the correct PCR for the measure rules. + */ +static void __init ima_add_diglim_flag(void) +{ + struct ima_rule_entry *entry; + + if (!IS_ENABLED(CONFIG_DIGLIM)) + return; + + if (!ima_measure_diglim && !ima_use_appraise_diglim) + return; + + list_for_each_entry(entry, ima_rules, list) { + if (entry->action != IMA_MEASURE && + entry->action != IMA_APPRAISE) + continue; + + if (entry->action == IMA_MEASURE && !ima_measure_diglim) + continue; + + if (entry->action == IMA_APPRAISE && + !ima_use_appraise_diglim) + continue; + + switch (entry->func) { + case BPRM_CHECK: + fallthrough; + case CREDS_CHECK: + fallthrough; + case MMAP_CHECK: + fallthrough; + case FILE_CHECK: + fallthrough; + case MODULE_CHECK: + fallthrough; + case FIRMWARE_CHECK: + fallthrough; + case DIGEST_LIST_CHECK: + if (entry->action == IMA_MEASURE) { + entry->flags |= IMA_USE_DIGLIM_MEASURE; + entry->flags |= IMA_PCR; + entry->pcr = ima_diglim_pcr; + } else { + entry->flags |= IMA_USE_DIGLIM_APPRAISE; + } + break; + default: + break; + } + } +} + static int ima_appraise_flag(enum ima_hooks func) { if (func == MODULE_CHECK) @@ -989,7 +1082,14 @@ void __init ima_init_policy(void) atomic_set(&ima_setxattr_allowed_hash_algorithms, 0); + if (ima_measure_diglim) + add_rules(&diglim_measure_rule, 1, IMA_DEFAULT_POLICY, 0); + + if (ima_use_appraise_diglim) + add_rules(&diglim_appraise_rule, 1, IMA_DEFAULT_POLICY, 0); + ima_update_policy_flags(); + ima_add_diglim_flag(); } /* Make sure we have a valid policy, at least containing some rules. */ From patchwork Thu Sep 30 11:55:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528105 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85855C4167D for ; Thu, 30 Sep 2021 11:55:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6829661A03 for ; Thu, 30 Sep 2021 11:55:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350549AbhI3L5d (ORCPT ); Thu, 30 Sep 2021 07:57:33 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3898 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350600AbhI3L5b (ORCPT ); Thu, 30 Sep 2021 07:57:31 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs7q02VQz67MlK; Thu, 30 Sep 2021 19:53:11 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:55:46 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 4/7] ima: Query file digest and retrieve info from its digest lists Date: Thu, 30 Sep 2021 13:55:30 +0200 Message-ID: <20210930115533.878169-5-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: If a file is going to be measured or appraised, and the use_diglim keyword has been added to the matching rule, query the calculated file digest with DIGLIM and retrieve some information: the actions (logical OR) done on the digest lists containing that digest; modifiers (logical OR) associated to the type. Retrieved actions and modifiers will be then processed by the corresponding IMA submodules. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_main.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index cde2e1c2a6be..550805b79984 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "../integrity.h" diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index fe1f4ef1bb9d..b32c4f8d19ea 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -198,6 +198,20 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } +static void diglim_file_digest_lookup(struct file *file, + struct integrity_iint_cache *iint, + int action, u16 *modifiers, u8 *actions) +{ + if ((file->f_mode & FMODE_CREATED) && !i_size_read(file_inode(file))) + return; + + if (!(iint->flags & IMA_COLLECTED)) + return; + + diglim_digest_get_info(iint->ima_hash->digest, iint->ima_hash->algo, + COMPACT_FILE, modifiers, actions); +} + static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, enum ima_hooks func) @@ -209,6 +223,8 @@ static int process_measurement(struct file *file, const struct cred *cred, char filename[NAME_MAX]; const char *pathname = NULL; u64 action; + u16 file_modifiers = 0; + u8 file_actions = 0; int rc = 0, must_appraise = 0; int pcr = CONFIG_IMA_MEASURE_PCR_IDX; struct evm_ima_xattr_data *xattr_value = NULL; @@ -344,6 +360,11 @@ static int process_measurement(struct file *file, const struct cred *cred, if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ pathname = ima_d_path(&file->f_path, &pathbuf, filename); + if (iint->flags & IMA_USE_DIGLIM_MEASURE || + iint->flags & IMA_USE_DIGLIM_APPRAISE) + diglim_file_digest_lookup(file, iint, action, &file_modifiers, + &file_actions); + if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { rc = ima_check_blacklist(iint, modsig, pcr); if (rc != -EPERM) { From patchwork Thu Sep 30 11:55:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528109 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C1E0C433F5 for ; Thu, 30 Sep 2021 11:57:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA3D961507 for ; Thu, 30 Sep 2021 11:57:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350643AbhI3L6n (ORCPT ); Thu, 30 Sep 2021 07:58:43 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3900 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350553AbhI3L6m (ORCPT ); Thu, 30 Sep 2021 07:58:42 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.206]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs8r5ryKz687L9; Thu, 30 Sep 2021 19:54:04 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:56:57 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 5/7] ima: Query metadata digest and retrieve info from its digest lists Date: Thu, 30 Sep 2021 13:55:31 +0200 Message-ID: <20210930115533.878169-6-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: First, introduce the new function evm_get_hash() to obtain the EVM digest of file metadata. The EVM digest is calculated depending on the passed security.evm type. Then, introduce the new function diglim_metadata_digest_lookup(), to search the metadata digest obtained from evm_get_hash() with type EVM_XATTR_PORTABLE_DIGSIG in the DIGLIM hash table and to obtain the actions and modifiers (logical OR) associated to the EVM digest, taken from the digest lists that contain that digest. Retrieved actions and modifiers will be then processed by the corresponding IMA submodules. Signed-off-by: Roberto Sassu --- include/linux/evm.h | 14 +++++++++ security/integrity/evm/evm_main.c | 40 ++++++++++++++++++++++++ security/integrity/ima/ima_main.c | 51 +++++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/linux/evm.h b/include/linux/evm.h index 4c374be70247..92856a7dbcab 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -11,6 +11,7 @@ #include #include +#include struct integrity_iint_cache; @@ -42,6 +43,10 @@ extern int evm_protected_xattr_if_enabled(const char *req_xattr_name); extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, int buffer_size, char type, bool canonical_fmt); +extern int evm_get_hash(struct dentry *dentry, const char *req_xattr_name, + const char *req_xattr_value, size_t req_xattr_value_len, + char type, enum hash_algo algo, u8 *digest, + size_t digest_len); #ifdef CONFIG_FS_POSIX_ACL extern int posix_xattr_acl(const char *xattrname); #else @@ -129,6 +134,15 @@ static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, { return -EOPNOTSUPP; } +static inline int evm_get_hash(struct dentry *dentry, + const char *req_xattr_name, + const char *req_xattr_value, + size_t req_xattr_value_len, char type, + enum hash_algo algo, u8 *digest, + size_t digest_len) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_EVM */ #endif /* LINUX_EVM_H */ diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index a8d7c761853e..3d45873f9266 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -429,6 +429,46 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry, } EXPORT_SYMBOL_GPL(evm_verifyxattr); +/** + * evm_get_hash - obtain the EVM digest calculated according to the passed type + * @dentry: object the EVM digest is calculated from + * @req_xattr_name: requested xattr + * @req_xattr_value: requested xattr value + * @req_xattr_value_len: requested xattr value length + * @type: requested security.evm type + * @algo: requested EVM digest algorithm + * @digest: the buffer the EVM digest is written to + * @digest_len: size of the buffer + * + * Calculate the EVM digest from metadata according to the passed security.evm + * type. + * + * Returns 0 if the digest has been calculated successfully, a negative value + * otherwise. + * + * This function requires the caller to lock the inode's i_mutex before it + * is executed. + */ +int evm_get_hash(struct dentry *dentry, const char *req_xattr_name, + const char *req_xattr_value, size_t req_xattr_value_len, + char type, enum hash_algo algo, u8 *digest, size_t digest_len) +{ + struct evm_digest evm_digest; + int rc; + + if (digest_len < hash_digest_size[algo]) + return -EINVAL; + + evm_digest.hdr.algo = algo; + rc = evm_calc_hash(dentry, req_xattr_name, req_xattr_value, + req_xattr_value_len, type, &evm_digest); + if (rc < 0) + return rc; + + memcpy(digest, evm_digest.digest, hash_digest_size[algo]); + return 0; +} + /* * evm_verify_current_integrity - verify the dentry's metadata integrity * @dentry: pointer to the affected dentry diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b32c4f8d19ea..84ccb76f6c3c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -212,6 +213,44 @@ static void diglim_file_digest_lookup(struct file *file, COMPACT_FILE, modifiers, actions); } +static void diglim_metadata_digest_lookup(struct file *file, + struct integrity_iint_cache *iint, + int action, + struct evm_ima_xattr_data *xattr_value, + int xattr_len, u16 *modifiers, + u8 *actions) +{ + u8 digest[IMA_MAX_DIGEST_SIZE]; + struct evm_xattr fake_ima_xattr; + struct evm_ima_xattr_data *ima_xattr = xattr_value; + int rc; + + if ((file->f_mode & FMODE_CREATED) && !i_size_read(file_inode(file))) + return; + + if (!(iint->flags & IMA_COLLECTED)) + return; + + if (!xattr_value) { + fake_ima_xattr.data.type = IMA_XATTR_DIGEST_NG; + fake_ima_xattr.data.data[0] = iint->ima_hash->algo; + memcpy(&fake_ima_xattr.data.data[1], iint->ima_hash->digest, + hash_digest_size[iint->ima_hash->algo]); + ima_xattr = &fake_ima_xattr.data; + xattr_len = 2 + hash_digest_size[iint->ima_hash->algo]; + } + + rc = evm_get_hash(file_dentry(file), XATTR_NAME_IMA, + (const char *)ima_xattr, xattr_len, + EVM_XATTR_PORTABLE_DIGSIG, iint->ima_hash->algo, + digest, sizeof(digest)); + if (rc < 0) + return; + + diglim_digest_get_info(digest, iint->ima_hash->algo, COMPACT_METADATA, + modifiers, actions); +} + static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, enum ima_hooks func) @@ -223,8 +262,8 @@ static int process_measurement(struct file *file, const struct cred *cred, char filename[NAME_MAX]; const char *pathname = NULL; u64 action; - u16 file_modifiers = 0; - u8 file_actions = 0; + u16 file_modifiers = 0, metadata_modifiers = 0; + u8 file_actions = 0, metadata_actions = 0; int rc = 0, must_appraise = 0; int pcr = CONFIG_IMA_MEASURE_PCR_IDX; struct evm_ima_xattr_data *xattr_value = NULL; @@ -361,9 +400,15 @@ static int process_measurement(struct file *file, const struct cred *cred, pathname = ima_d_path(&file->f_path, &pathbuf, filename); if (iint->flags & IMA_USE_DIGLIM_MEASURE || - iint->flags & IMA_USE_DIGLIM_APPRAISE) + iint->flags & IMA_USE_DIGLIM_APPRAISE) { diglim_file_digest_lookup(file, iint, action, &file_modifiers, &file_actions); + inode_lock(inode); + diglim_metadata_digest_lookup(file, iint, action, xattr_value, + xattr_len, &metadata_modifiers, + &metadata_actions); + inode_unlock(inode); + } if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { rc = ima_check_blacklist(iint, modsig, pcr); From patchwork Thu Sep 30 11:55:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528111 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24FD5C4332F for ; Thu, 30 Sep 2021 11:57:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0324C61425 for ; Thu, 30 Sep 2021 11:57:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350690AbhI3L6n (ORCPT ); Thu, 30 Sep 2021 07:58:43 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3901 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350600AbhI3L6m (ORCPT ); Thu, 30 Sep 2021 07:58:42 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs8W5mVPz67vP9; Thu, 30 Sep 2021 19:53:47 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:56:58 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 6/7] ima: Skip measurement of files found in DIGLIM hash table Date: Thu, 30 Sep 2021 13:55:32 +0200 Message-ID: <20210930115533.878169-7-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Skip a file measurement if the IMA policy allows the usage of DIGLIM with the use_diglim directive, if the content or metadata digests were found in the DIGLIM hash table and if at least one of the digest lists containing the found digest has the action COMPACT_ACTION_IMA_MEASURED set. Since the usage of the use_diglim directive requires to specify a different PCR than the default one, this avoids confusion with the standard IMA measurement list where if a file is missing it means that it was not accessed. The new meaning of measurements done with the use_diglim directive is that if a file is missing, it was not accessed or it was accessed, was found in the DIGLIM hash table, and the measurement of at least one digest list containing its content or metadata digest is in the measurement list. Files not found in the DIGLIM hash table or files whose content or metadata digest was not measured will still appear in the measurement list. Given that with the new behavior it cannot be determined whether a file was accessed or not, remote verifiers must assume the worst case where every file, whose content or metadata digest is in a measured digest list, was accessed. With this assumption, it is safe to assume the measurement list generated with the new behavior as complete. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 84ccb76f6c3c..7add0e70f67a 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -442,6 +442,15 @@ static int process_measurement(struct file *file, const struct cred *cred, if (must_appraise) if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) action &= ~(IMA_MEASURE | IMA_AUDIT); + /* Use DIGLIM method for measurement if enabled in the policy. */ + if (action & IMA_MEASURE && (iint->flags & IMA_USE_DIGLIM_MEASURE)) { + if (file_actions & (1 << COMPACT_ACTION_IMA_MEASURED) || + metadata_actions & (1 << COMPACT_ACTION_IMA_MEASURED)) { + iint->flags |= IMA_MEASURED; + iint->measured_pcrs |= (0x1 << pcr); + action &= ~IMA_MEASURE; + } + } if (action & IMA_MEASURE) ima_store_measurement(iint, file, pathname, xattr_value, xattr_len, modsig, pcr, From patchwork Thu Sep 30 11:55:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 12528113 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8964FC433FE for ; Thu, 30 Sep 2021 11:57:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6C606619FA for ; Thu, 30 Sep 2021 11:57:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350644AbhI3L6o (ORCPT ); Thu, 30 Sep 2021 07:58:44 -0400 Received: from frasgout.his.huawei.com ([185.176.79.56]:3902 "EHLO frasgout.his.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1350691AbhI3L6n (ORCPT ); Thu, 30 Sep 2021 07:58:43 -0400 Received: from fraeml714-chm.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4HKs8X2nRYz685Yr; Thu, 30 Sep 2021 19:53:48 +0800 (CST) Received: from roberto-ThinkStation-P620.huawei.com (10.204.63.22) by fraeml714-chm.china.huawei.com (10.206.15.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Thu, 30 Sep 2021 13:56:59 +0200 From: Roberto Sassu To: , , CC: , , , Roberto Sassu Subject: [RFC][PATCH 7/7] ima: Add support for appraisal with digest lists Date: Thu, 30 Sep 2021 13:55:33 +0200 Message-ID: <20210930115533.878169-8-roberto.sassu@huawei.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210930115533.878169-1-roberto.sassu@huawei.com> References: <20210930115533.878169-1-roberto.sassu@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.63.22] X-ClientProxiedBy: lhreml752-chm.china.huawei.com (10.201.108.202) To fraeml714-chm.china.huawei.com (10.206.15.33) X-CFilter-Loop: Reflected Precedence: bulk List-ID: Introduce a new appraisal method based on the lookup of the file and metadata digest in the DIGLIM hash table, enabled with the use_diglim directive. First pass to ima_appraise_measurement() the actions performed on the digest lists containing the found digests. Then, consider the metadata verification as successful if EVM returned the status INTEGRITY_NOLABEL (no security.evm), if the metadata digest was found in the DIGLIM hash table and at least one digest list containing it was succefully appraised with a signature. Finally, consider the file content verification as successful if there is no security.ima or appended signature, if the file or metadata digest (calculated with the actual file digest) were found in the DIGLIM hash table and at least one digest list containing it has a valid signature. Furthermore, mark the file as immutable if the COMPACT_MOD_IMMUTABLE modifier was set in the header of the digest lists containing the found digests. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima.h | 4 ++- security/integrity/ima/ima_appraise.c | 37 +++++++++++++++++++++++---- security/integrity/ima/ima_main.c | 6 ++++- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 550805b79984..631e9e4c343b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -319,7 +319,9 @@ 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 xattr_len, const struct modsig *modsig, + u16 file_modifiers, u8 file_actions, + u16 metadata_modifiers, u8 metadata_actions); int ima_must_appraise(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); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index e1b9a5bc4252..a0885272411e 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -377,7 +377,9 @@ 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 xattr_len, const struct modsig *modsig, + u16 file_modifiers, u8 file_actions, + u16 metadata_modifiers, u8 metadata_actions) { static const char op[] = "appraise_data"; const char *cause = "unknown"; @@ -387,12 +389,26 @@ int ima_appraise_measurement(enum ima_hooks func, int rc = xattr_len; bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; - /* If not appraising a modsig, we need an xattr. */ - if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) + /* We are interested only in appraisal-related flags. */ + file_actions &= COMPACT_ACTION_IMA_APPRAISED_DIGSIG; + metadata_actions &= COMPACT_ACTION_IMA_APPRAISED_DIGSIG; + + /* Disable DIGLIM method for appraisal if not enabled in the policy. */ + if (!(iint->flags & IMA_USE_DIGLIM_APPRAISE)) { + file_actions = 0; + metadata_actions = 0; + } + + /* If not appraising a modsig or using DIGLIM, we need an xattr. */ + if (!(inode->i_opflags & IOP_XATTR) && !try_modsig && + !file_actions && !metadata_actions) return INTEGRITY_UNKNOWN; - /* If reading the xattr failed and there's no modsig, error out. */ - if (rc <= 0 && !try_modsig) { + /* + * If reading the xattr failed, there's no modsig and the DIGLIM + * appraisal method is not available, error out. + */ + if (rc <= 0 && !try_modsig && !file_actions && !metadata_actions) { if (rc && rc != -ENODATA) goto out; @@ -420,6 +436,10 @@ int ima_appraise_measurement(enum ima_hooks func, break; fallthrough; case INTEGRITY_NOLABEL: /* No security.evm xattr. */ + if (metadata_actions) { + status = INTEGRITY_PASS_IMMUTABLE; + break; + } cause = "missing-HMAC"; goto out; case INTEGRITY_FAIL_IMMUTABLE: @@ -455,6 +475,13 @@ int ima_appraise_measurement(enum ima_hooks func, rc == -ENOKEY)) rc = modsig_verify(func, modsig, &status, &cause); + if (!xattr_value && !try_modsig && (file_actions || metadata_actions)) { + status = INTEGRITY_PASS; + + if ((file_modifiers & (1 << COMPACT_MOD_IMMUTABLE)) || + (metadata_modifiers & (1 << COMPACT_MOD_IMMUTABLE))) + set_bit(IMA_DIGSIG, &iint->atomic_flags); + } out: /* * File signatures on some filesystems can not be properly verified. diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7add0e70f67a..7a9a2392d49c 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -416,7 +416,11 @@ static int process_measurement(struct file *file, const struct cred *cred, inode_lock(inode); rc = ima_appraise_measurement(func, iint, file, pathname, xattr_value, - xattr_len, modsig); + xattr_len, modsig, + file_modifiers, + file_actions, + metadata_modifiers, + metadata_actions); inode_unlock(inode); } if (!rc)