From patchwork Wed Nov 27 01:56:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263215 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F98014ED for ; Wed, 27 Nov 2019 01:57:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1A7BC20836 for ; Wed, 27 Nov 2019 01:57:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="kTVhIKSD" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726618AbfK0B5E (ORCPT ); Tue, 26 Nov 2019 20:57:04 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54452 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726121AbfK0B5E (ORCPT ); Tue, 26 Nov 2019 20:57:04 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id DD9E72010BBA; Tue, 26 Nov 2019 17:57:03 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com DD9E72010BBA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819823; bh=Hygomg0IkjBeTUP6XSMjFJvucT6fovHpF5/8RvY72oU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kTVhIKSDlOcFNc/XBtP9aJ8tCmW3I8IChJt2RT+1KN90MLAgzsHAR7HKowdHi8sqw hCP9zg/rl2IWcbGlvdKrFcRTii3XZiz7JRx+VgWC06WeBp5UEQUIkRHsciVHIqHI9V Xn7LrrNeffb6hG8zdX2bCVE7EYaUR03JQBHBgReE= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 1/6] IMA: Check IMA policy flag Date: Tue, 26 Nov 2019 17:56:49 -0800 Message-Id: <20191127015654.3744-2-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Return immediately from process_buffer_measurement() if the IMA policy flag is set to zero. Not doing this can result in kernel panic when process_buffer_measurement() is called before IMA is initialized (for instance, when the IMA hook is called when a key is added to the .builtin_trusted_keys keyring). This change adds the check in process_buffer_measurement() to return immediately if ima_policy_flag is set to zero. Signed-off-by: Lakshmi Ramasubramanian --- security/integrity/ima/ima_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index d7e987baf127..9b35db2fc777 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -655,6 +655,9 @@ void process_buffer_measurement(const void *buf, int size, int action = 0; u32 secid; + if (!ima_policy_flag) + return; + /* * Both LSM hooks and auxilary based buffer measurements are * based on policy. To avoid code duplication, differentiate From patchwork Wed Nov 27 01:56:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263227 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A1B14DB for ; Wed, 27 Nov 2019 01:57:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 105BF20835 for ; Wed, 27 Nov 2019 01:57:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="WMYoQG9W" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726909AbfK0B5F (ORCPT ); Tue, 26 Nov 2019 20:57:05 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54464 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726346AbfK0B5E (ORCPT ); Tue, 26 Nov 2019 20:57:04 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id 159EA20B4900; Tue, 26 Nov 2019 17:57:04 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 159EA20B4900 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819824; bh=L4puKXt7OmrSagN42Huxd1vQTKOco/JYM8kKj45zf2k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WMYoQG9WHtZ0hB4PRgf16yChjYX6bz917ovKRu85etAEK6XZJrjmYdxMQJDaDpbeO s5DlDbrk9i/kYlif26j/bZGCL+Virqw6BU/JNT8NyUYVxj9Rn5UVWhpQwDrBOySbfw WpR6FZoP2BXNT2PnfTBfCQPEzjePqMruGkBvLb3E= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 2/6] IMA: Add KEY_CHECK func to measure keys Date: Tue, 26 Nov 2019 17:56:50 -0800 Message-Id: <20191127015654.3744-3-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Measure keys loaded onto any keyring. This patch defines a new IMA policy func namely KEY_CHECK to measure keys. Updated ima_match_rules() to check for KEY_CHECK and ima_parse_rule() to handle KEY_CHECK. Signed-off-by: Lakshmi Ramasubramanian --- Documentation/ABI/testing/ima_policy | 6 +++++- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_policy.c | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 29aaedf33246..066d32797500 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -29,7 +29,7 @@ Description: base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] - [KEXEC_CMDLINE] + [KEXEC_CMDLINE] [KEY_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value @@ -113,3 +113,7 @@ Description: Example of appraise rule allowing modsig appended signatures: appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig + + Example of measure rule using KEY_CHECK to measure all keys: + + measure func=KEY_CHECK diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index df4ca482fb53..fe6c698617bd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -193,6 +193,7 @@ static inline unsigned long ima_hash_key(u8 *digest) hook(KEXEC_INITRAMFS_CHECK) \ hook(POLICY_CHECK) \ hook(KEXEC_CMDLINE) \ + hook(KEY_CHECK) \ hook(MAX_CHECK) #define __ima_hook_enumify(ENUM) ENUM, diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index f19a895ad7cd..1525a28fd705 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -373,7 +373,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, { int i; - if (func == KEXEC_CMDLINE) { + if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { if ((rule->flags & IMA_FUNC) && (rule->func == func)) return true; return false; @@ -997,6 +997,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) entry->func = POLICY_CHECK; else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0) entry->func = KEXEC_CMDLINE; + else if (strcmp(args[0].from, "KEY_CHECK") == 0) + entry->func = KEY_CHECK; else result = -EINVAL; if (!result) From patchwork Wed Nov 27 01:56:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263223 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 40FDC17F0 for ; Wed, 27 Nov 2019 01:57:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1F8552080F for ; Wed, 27 Nov 2019 01:57:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="pDYDh5z4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727113AbfK0B5Q (ORCPT ); Tue, 26 Nov 2019 20:57:16 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54476 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726529AbfK0B5F (ORCPT ); Tue, 26 Nov 2019 20:57:05 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id 3C34620B9C38; Tue, 26 Nov 2019 17:57:04 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 3C34620B9C38 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819824; bh=srUE+MXxJSaGXWC97Ag7dvG9PBXTJJkJz1xT39vmckg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pDYDh5z4Azw15Y2qC/B1aCi7illRZ21icFpZL/+/6zWbeRkjJM+jPLan1BLfrcNlU EerpN07XBoOiTIT/tbR6XmGYNsEffiXXfknMetFfdw4bwbShvY7ZFTsCdjhCIyD/IF kQ5Hth7pf7A+Bas6yrmdDsZWvGQNQebnkrA5CjL0= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 3/6] IMA: Define an IMA hook to measure keys Date: Tue, 26 Nov 2019 17:56:51 -0800 Message-Id: <20191127015654.3744-4-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Measure asymmetric keys used for verifying file signatures, certificates, etc. This patch defines a new IMA hook namely ima_post_key_create_or_update() to measure the payload used to create a new key or update an existing key. The IMA hook is defined in a new file namely ima_asymmetric_keys.c which is built only if CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE is enabled. Signed-off-by: Lakshmi Ramasubramanian --- security/integrity/ima/Makefile | 1 + security/integrity/ima/ima_asymmetric_keys.c | 52 ++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 security/integrity/ima/ima_asymmetric_keys.c diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 31d57cdf2421..207a0a9eb72c 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -12,3 +12,4 @@ ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o +obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += ima_asymmetric_keys.o diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c new file mode 100644 index 000000000000..2308adcdeff3 --- /dev/null +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Microsoft Corporation + * + * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com) + * + * File: ima_asymmetric_keys.c + * Defines an IMA hook to measure asymmetric keys on key + * create or update. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include "ima.h" + +/** + * ima_post_key_create_or_update - measure asymmetric keys + * @keyring: keyring to which the key is linked to + * @key: created or updated key + * @payload: The data used to instantiate or update the key. + * @plen: The length of @payload. + * @flags: key flags + * @create: flag indicating whether the key was created or updated + * + * Keys can only be measured, not appraised. + * The payload data used to instantiate or update the key is measured. + */ +void ima_post_key_create_or_update(struct key *keyring, struct key *key, + const void *payload, size_t plen, + unsigned long flags, bool create) +{ + /* Only asymmetric keys are handled by this hook. */ + if (key->type != &key_type_asymmetric) + return; + + if (!payload || (plen == 0)) + return; + + /* + * keyring->description points to the name of the keyring + * (such as ".builtin_trusted_keys", ".ima", etc.) to + * which the given key is linked to. + * + * The name of the keyring is passed in the "eventname" + * parameter to process_buffer_measurement() and is set + * in the "eventname" field in ima_event_data for + * the key measurement IMA event. + */ + process_buffer_measurement(payload, plen, + keyring->description, KEY_CHECK, 0); +} From patchwork Wed Nov 27 01:56:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263225 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0662114DB for ; Wed, 27 Nov 2019 01:57:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D94F92080F for ; Wed, 27 Nov 2019 01:57:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="FvpiQSsi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726529AbfK0B5X (ORCPT ); Tue, 26 Nov 2019 20:57:23 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54496 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726593AbfK0B5F (ORCPT ); Tue, 26 Nov 2019 20:57:05 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id 662FB2010BBB; Tue, 26 Nov 2019 17:57:04 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 662FB2010BBB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819824; bh=xcEW1XwmfmUqNILSNIKCMPh/1lYTBQkm7M1N6MJsBow=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FvpiQSsiBqs7ALnEiu18QKTQpj1+Yjlp62dXQUAmT/LTbEc5Y+m0fvq9K0NI0J/Ju D92ppvb/yisFda8PFk53J5gaiSyOJJ12WwSzlSY1jHvOZNMfgNmD/hrw5UDomG8Yzd tUCXNIVGz6Q02R9qDRXmB4v6ir+/VZKyRzS2voOs= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 4/6] KEYS: Call the IMA hook to measure keys Date: Tue, 26 Nov 2019 17:56:52 -0800 Message-Id: <20191127015654.3744-5-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Call the IMA hook from key_create_or_update() function to measure the payload when a new key is created or an existing key is updated. This patch adds the call to the IMA hook from key_create_or_update() function to measure the key on key create or update. Signed-off-by: Lakshmi Ramasubramanian --- include/linux/ima.h | 14 ++++++++++++++ security/keys/key.c | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/linux/ima.h b/include/linux/ima.h index 6d904754d858..3b89136bc218 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -101,6 +101,20 @@ static inline void ima_add_kexec_buffer(struct kimage *image) {} #endif +#if defined(CONFIG_IMA) && defined(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) +extern void ima_post_key_create_or_update(struct key *keyring, + struct key *key, + const void *payload, size_t plen, + unsigned long flags, bool create); +#else +static inline void ima_post_key_create_or_update(struct key *keyring, + struct key *key, + const void *payload, + size_t plen, + unsigned long flags, + bool create) {} +#endif /* CONFIG_IMA && CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE */ + #ifdef CONFIG_IMA_APPRAISE extern bool is_ima_appraise_enabled(void); extern void ima_inode_post_setattr(struct dentry *dentry); diff --git a/security/keys/key.c b/security/keys/key.c index 764f4c57913e..718bf7217420 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "internal.h" @@ -936,6 +937,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto error_link_end; } + ima_post_key_create_or_update(keyring, key, payload, plen, + flags, true); + key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_link_end: @@ -965,6 +969,12 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } key_ref = __key_update(key_ref, &prep); + + if (!IS_ERR(key_ref)) + ima_post_key_create_or_update(keyring, key, + payload, plen, + flags, false); + goto error_free_prep; } EXPORT_SYMBOL(key_create_or_update); From patchwork Wed Nov 27 01:56:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263219 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B63B014DB for ; Wed, 27 Nov 2019 01:57:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8CA48207DD for ; Wed, 27 Nov 2019 01:57:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="S/dcOesZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726696AbfK0B5I (ORCPT ); Tue, 26 Nov 2019 20:57:08 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54506 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726852AbfK0B5G (ORCPT ); Tue, 26 Nov 2019 20:57:06 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id 8B07020BBF29; Tue, 26 Nov 2019 17:57:04 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 8B07020BBF29 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819824; bh=FkS8WUgBPtrBLFKpxjU/ucJJORKFo6V23HsfAIH44p8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S/dcOesZQahkGAYdX6ujJQ4krPbqqnynBwZS8qYzo8/Bie+LBeX4Kn3MP/eCTlHoo yWRamOvGc53ROJWuVcSfR/CK3naqLPOIyEK/UnJZ0ry1Yh7YZhCMHd9EMYDf9rtyuP Xy2cOtTtMvG13PS3q3SWEHZ+al8FYU7q/bo1FD8E= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 5/6] IMA: Add support to limit measuring keys Date: Tue, 26 Nov 2019 17:56:53 -0800 Message-Id: <20191127015654.3744-6-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Limit measuring keys to those keys being loaded onto a given set of keyrings only. This patch defines a new IMA policy option namely "keyrings=" that can be used to specify a set of keyrings. If this option is specified in the policy for "measure func=KEY_CHECK" then only the keys loaded onto a keyring given in the "keyrings=" option are measured. Added a new parameter namely "keyring" (name of the keyring) to process_buffer_measurement(). The keyring name is passed to ima_get_action() to determine the required action. ima_match_rules() is updated to check keyring in the policy, if specified, for KEY_CHECK function. Signed-off-by: Lakshmi Ramasubramanian --- Documentation/ABI/testing/ima_policy | 10 ++- security/integrity/ima/ima.h | 8 ++- security/integrity/ima/ima_api.c | 8 ++- security/integrity/ima/ima_appraise.c | 4 +- security/integrity/ima/ima_asymmetric_keys.c | 8 ++- security/integrity/ima/ima_main.c | 9 +-- security/integrity/ima/ima_policy.c | 67 ++++++++++++++++++-- 7 files changed, 96 insertions(+), 18 deletions(-) diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 066d32797500..cd572912c593 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -25,7 +25,7 @@ Description: lsm: [[subj_user=] [subj_role=] [subj_type=] [obj_user=] [obj_role=] [obj_type=]] option: [[appraise_type=]] [template=] [permit_directio] - [appraise_flag=] + [appraise_flag=] [keyrings=] base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] @@ -42,6 +42,9 @@ Description: appraise_flag:= [check_blacklist] Currently, blacklist check is only for files signed with appended signature. + keyrings:= list of keyrings + (eg, .builtin_trusted_keys|.ima). Only valid + when action is "measure" and func is KEY_CHECK. template:= name of a defined IMA template type (eg, ima-ng). Only valid when action is "measure". pcr:= decimal value @@ -117,3 +120,8 @@ Description: Example of measure rule using KEY_CHECK to measure all keys: measure func=KEY_CHECK + + Example of measure rule using KEY_CHECK to only measure + keys added to .builtin_trusted_keys or .ima keyring: + + measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index fe6c698617bd..f06238e41a7c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -208,7 +208,8 @@ struct modsig; /* LIM API function definitions */ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, - struct ima_template_desc **template_desc); + struct ima_template_desc **template_desc, + const char *keyring); 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, @@ -220,7 +221,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, struct ima_template_desc *template_desc); void process_buffer_measurement(const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr); + int pcr, const char *keyring); void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename); int ima_alloc_init_template(struct ima_event_data *event_data, @@ -235,7 +236,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); /* IMA policy related functions */ int ima_match_policy(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); + struct ima_template_desc **template_desc, + const char *keyring); void ima_init_policy(void); void ima_update_policy(void); void ima_update_policy_flag(void); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 610759fe63b8..f6bc00914aa5 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -169,12 +169,13 @@ void ima_add_violation(struct file *file, const unsigned char *filename, * @func: caller identifier * @pcr: pointer filled in if matched measure policy sets pcr= * @template_desc: pointer filled in if matched measure policy sets template= + * @keyring: keyring name used to determine the action * * The policy is defined in terms of keypairs: * subj=, obj=, type=, func=, mask=, fsmagic= * subj,obj, and type: are LSM specific. * func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK - * | KEXEC_CMDLINE + * | KEXEC_CMDLINE | KEY_CHECK * mask: contains the permission mask * fsmagic: hex value * @@ -183,14 +184,15 @@ void ima_add_violation(struct file *file, const unsigned char *filename, */ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, - struct ima_template_desc **template_desc) + struct ima_template_desc **template_desc, + const char *keyring) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; flags &= ima_policy_flag; return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, - template_desc); + template_desc, keyring); } /* diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 300c8d2943c5..a9649b04b9f1 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -55,7 +55,7 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) security_task_getsecid(current, &secid); return ima_match_policy(inode, current_cred(), secid, func, mask, - IMA_APPRAISE | IMA_HASH, NULL, NULL); + IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); } static int ima_fix_xattr(struct dentry *dentry, @@ -330,7 +330,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) process_buffer_measurement(digest, digestsize, "blacklisted-hash", NONE, - pcr); + pcr, NULL); } return rc; diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index 2308adcdeff3..ca895f9a6504 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -46,7 +46,13 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, * parameter to process_buffer_measurement() and is set * in the "eventname" field in ima_event_data for * the key measurement IMA event. + * + * The name of the keyring is also passed in the "keyring" + * parameter to process_buffer_measurement() to check + * if the IMA policy is configured to measure a key linked + * to the given keyring. */ process_buffer_measurement(payload, plen, - keyring->description, KEY_CHECK, 0); + keyring->description, KEY_CHECK, 0, + keyring->description); } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9b35db2fc777..2272c3255c7d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -215,7 +215,7 @@ static int process_measurement(struct file *file, const struct cred *cred, * Included is the appraise submask. */ action = ima_get_action(inode, cred, secid, mask, func, &pcr, - &template_desc); + &template_desc, NULL); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) @@ -632,12 +632,13 @@ int ima_load_data(enum kernel_load_data_id id) * @eventname: event name to be used for the buffer entry. * @func: IMA hook * @pcr: pcr to extend the measurement + * @keyring: keyring name to determine the action to be performed * * Based on policy, the buffer is measured into the ima log. */ void process_buffer_measurement(const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr) + int pcr, const char *keyring) { int ret = 0; struct ima_template_entry *entry = NULL; @@ -668,7 +669,7 @@ void process_buffer_measurement(const void *buf, int size, if (func) { security_task_getsecid(current, &secid); action = ima_get_action(NULL, current_cred(), secid, 0, func, - &pcr, &template); + &pcr, &template, keyring); if (!(action & IMA_MEASURE)) return; } @@ -721,7 +722,7 @@ void ima_kexec_cmdline(const void *buf, int size) { if (buf && size != 0) process_buffer_measurement(buf, size, "kexec-cmdline", - KEXEC_CMDLINE, 0); + KEXEC_CMDLINE, 0, NULL); } static int __init init_ima(void) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 1525a28fd705..d9400585fcda 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -79,6 +79,7 @@ struct ima_rule_entry { int type; /* audit type */ } lsm[MAX_LSM_RULES]; char *fsname; + char *keyrings; /* Measure keys added to these keyrings */ struct ima_template_desc *template; }; @@ -356,6 +357,55 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, return NOTIFY_OK; } +/** + * ima_match_keyring - determine whether the keyring matches the measure rule + * @rule: a pointer to a rule + * @keyring: name of the keyring to match against the measure rule + * + * If the measure action for KEY_CHECK does not specify keyrings= + * option then return true (Measure all keys). + * Else, return true if the given keyring name is present in + * the keyrings= option. False, otherwise. + */ +static bool ima_match_keyring(struct ima_rule_entry *rule, + const char *keyring) +{ + const char *p; + + /* If "keyrings=" is not specified all keys are measured. */ + if (!rule->keyrings) + return true; + + if (!keyring) + return false; + + /* + * "keyrings=" is specified in the policy in the format below: + * keyrings=.builtin_trusted_keys|.ima|.evm + * + * Each keyring name in the option is separated by a '|' and + * the last keyring name is null terminated. + * + * The given keyring is considered matched only if + * the whole keyring name matched a keyring name specified + * in the "keyrings=" option. + */ + p = strstr(rule->keyrings, keyring); + if (p) { + /* + * Found a substring match. Check if the character + * at the end of the keyring name is | (keyring name + * separator) or is the terminating null character. + * If yes, we have a whole string match. + */ + p += strlen(keyring); + if (*p == '|' || *p == '\0') + return true; + } + + return false; +} + /** * ima_match_rules - determine whether an inode matches the measure rule. * @rule: a pointer to a rule @@ -364,18 +414,23 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, * @secid: the secid of the task to be validated * @func: LIM hook identifier * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) + * @keyring: keyring name to check in policy for KEY_CHECK func * * Returns true on rule match, false on failure. */ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, const struct cred *cred, u32 secid, - enum ima_hooks func, int mask) + enum ima_hooks func, int mask, + const char *keyring) { int i; if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { - if ((rule->flags & IMA_FUNC) && (rule->func == func)) + if ((rule->flags & IMA_FUNC) && (rule->func == func)) { + if (func == KEY_CHECK) + return ima_match_keyring(rule, keyring); return true; + } return false; } if ((rule->flags & IMA_FUNC) && @@ -479,6 +534,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) * @pcr: set the pcr to extend * @template_desc: the template that should be used for this rule + * @keyring: the keyring name, if given, to be used to check in the policy. + * keyring can be NULL if func is anything other than KEY_CHECK. * * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) * conditions. @@ -489,7 +546,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) */ int ima_match_policy(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) + struct ima_template_desc **template_desc, + const char *keyring) { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); @@ -503,7 +561,8 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, if (!(entry->action & actmask)) continue; - if (!ima_match_rules(entry, inode, cred, secid, func, mask)) + if (!ima_match_rules(entry, inode, cred, secid, func, mask, + keyring)) continue; action |= entry->flags & IMA_ACTION_FLAGS; From patchwork Wed Nov 27 01:56:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lakshmi Ramasubramanian X-Patchwork-Id: 11263217 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6BFC614ED for ; Wed, 27 Nov 2019 01:57:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 40F1020835 for ; Wed, 27 Nov 2019 01:57:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="lJIr1VWr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727031AbfK0B5I (ORCPT ); Tue, 26 Nov 2019 20:57:08 -0500 Received: from linux.microsoft.com ([13.77.154.182]:54514 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726876AbfK0B5F (ORCPT ); Tue, 26 Nov 2019 20:57:05 -0500 Received: from nramas-ThinkStation-P520.corp.microsoft.com (unknown [131.107.174.108]) by linux.microsoft.com (Postfix) with ESMTPSA id B0BC720BBF94; Tue, 26 Nov 2019 17:57:04 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com B0BC720BBF94 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1574819824; bh=6VkDuQtMfZ0JxsdKb2br0Z+5f0VVuOr0R9vAUsy6phY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lJIr1VWrpzeGxEYUAjoPwcjdHhhhKbfYADGJ+Q9l9QrroY3jjrsILcsAouv1qO040 ZZ4osXAsCw/sxUr9gpgfvig0AED4uCIW2gQmBa2xR0t8Pn5qM3QmOtKtMwgKs649J9 hTJ22NpZw5lGHIlwnx5NbgaxDLTqpgba0wK2ejKw= From: Lakshmi Ramasubramanian To: zohar@linux.ibm.com, linux-integrity@vger.kernel.org Cc: eric.snowberg@oracle.com, dhowells@redhat.com, matthewgarrett@google.com, sashal@kernel.org, jamorris@linux.microsoft.com, linux-kernel@vger.kernel.org, keyrings@vger.kernel.org Subject: [PATCH v9 6/6] IMA: Read keyrings= option from the IMA policy Date: Tue, 26 Nov 2019 17:56:54 -0800 Message-Id: <20191127015654.3744-7-nramas@linux.microsoft.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191127015654.3744-1-nramas@linux.microsoft.com> References: <20191127015654.3744-1-nramas@linux.microsoft.com> Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org Read "keyrings=" option, if specified in the IMA policy, and store in the list of IMA rules when the configured IMA policy is read. This patch defines a new policy token enum namely Opt_keyrings and an option flag IMA_KEYRINGS for reading "keyrings=" option from the IMA policy. Updated ima_parse_rule() to parse "keyrings=" option in the policy. Updated ima_policy_show() to display "keyrings=" option. The following example illustrates how key measurement can be verified. Sample IMA Policy entry to measure keys (Added in the file /etc/ima/ima-policy): measure func=KEY_CHECK keyrings=.ima|.evm template=ima-buf Build the kernel with this patch set applied and reboot to that kernel. Ensure the IMA policy is applied: root@nramas:/home/nramas# cat /sys/kernel/security/ima/policy measure func=KEY_CHECK keyrings=.ima|.evm template=ima-buf View the initial IMA measurement log: root@nramas:/home/nramas# cat /sys/kernel/security/ima/ascii_runtime_measurements 10 67ec... ima-ng sha1:b5466c508583f0e633df83aa58fc7c5b67ccf667 boot_aggregate Now, add a certificate (for example, x509_ima.der) to the .ima keyring using evmctl (IMA-EVM Utility) root@nramas:/home/nramas# keyctl show %:.ima Keyring 547515640 ---lswrv 0 0 keyring: .ima root@nramas:/home/nramas# evmctl import x509_ima.der 547515640 root@nramas:/home/nramas# keyctl show %:.ima Keyring 547515640 ---lswrv 0 0 keyring: .ima 809678766 --als--v 0 0 \_ asymmetric: hostname: whoami signing key: 052dd247dc3c36... View the updated IMA measurement log: root@nramas:/home/nramas# cat /sys/kernel/security/ima/ascii_runtime_measurements 10 67ec... ima-ng sha1:b5466c508583f0e633df83aa58fc7c5b67ccf667 boot_aggregate 10 3adf... ima-buf sha256:27c915b8ddb9fae7214cf0a8a7043cc3eeeaa7539bcb136f8427067b5f6c3b7b .ima 308202863082...4aee root@nramas:/home/nramas# For this sample, SHA256 should be selected as the hash algorithm used by IMA. The following command verifies if the SHA256 hash generated from the payload in the IMA log entry (listed above) for the .ima key matches the SHA256 hash in the IMA log entry. The output of this command should match the SHA256 hash given in the IMA log entry (In this case, it should be 27c915b8ddb9fae7214cf0a8a7043cc3eeeaa7539bcb136f8427067b5f6c3b7b) root@nramas:/home/nramas# cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements | grep 27c915b8ddb9fae7214cf0a8a7043cc3eeeaa7539bcb136f8427067b5f6c3b7b | cut -d' ' -f 6 | xxd -r -p |tee ima-cert.der | sha256sum | cut -d' ' -f 1 The above command also creates a binary file namely ima-cert.der using the payload in the IMA log entry. This file should be a valid x509 certificate which can be verified using openssl as given below: root@nramas:/home/nramas# openssl x509 -in ima-cert.der -inform DER -text The above command should display the contents of the file ima-cert.der as an x509 certificate. The IMA policy used here allows measurement of keys added to ".ima" and ".evm" keyrings only. Add a key to any other keyring and verify that the key is not measured. Signed-off-by: Lakshmi Ramasubramanian --- security/integrity/ima/ima_policy.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d9400585fcda..78b25f083fe1 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -34,6 +34,7 @@ #define IMA_EUID 0x0080 #define IMA_PCR 0x0100 #define IMA_FSNAME 0x0200 +#define IMA_KEYRINGS 0x0400 #define UNKNOWN 0 #define MEASURE 0x0001 /* same as IMA_MEASURE */ @@ -825,7 +826,8 @@ enum { Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, Opt_appraise_type, Opt_appraise_flag, - Opt_permit_directio, Opt_pcr, Opt_template, Opt_err + Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings, + Opt_err }; static const match_table_t policy_tokens = { @@ -861,6 +863,7 @@ static const match_table_t policy_tokens = { {Opt_permit_directio, "permit_directio"}, {Opt_pcr, "pcr=%s"}, {Opt_template, "template=%s"}, + {Opt_keyrings, "keyrings=%s"}, {Opt_err, NULL} }; @@ -1110,6 +1113,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) result = 0; entry->flags |= IMA_FSNAME; break; + case Opt_keyrings: + ima_log_string(ab, "keyrings", args[0].from); + + if ((entry->keyrings) || + (entry->action != MEASURE) || + (entry->func != KEY_CHECK)) { + result = -EINVAL; + break; + } + entry->keyrings = kstrdup(args[0].from, GFP_KERNEL); + if (!entry->keyrings) { + result = -ENOMEM; + break; + } + result = 0; + entry->flags |= IMA_KEYRINGS; + break; case Opt_fsuuid: ima_log_string(ab, "fsuuid", args[0].from); @@ -1485,6 +1505,13 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, " "); } + if (entry->flags & IMA_KEYRINGS) { + if (entry->keyrings != NULL) + snprintf(tbuf, sizeof(tbuf), "%s", entry->keyrings); + seq_printf(m, pt(Opt_keyrings), tbuf); + seq_puts(m, " "); + } + if (entry->flags & IMA_PCR) { snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr); seq_printf(m, pt(Opt_pcr), tbuf);