From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752571AbcFVNgJ (ORCPT ); Wed, 22 Jun 2016 09:36:09 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:42446 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752187AbcFVNf0 (ORCPT ); Wed, 22 Jun 2016 09:35:26 -0400 X-IBM-Helo: d23dlp02.au.ibm.com X-IBM-MailFrom: zohar@linux.vnet.ibm.com X-IBM-RcptTo: linux-kernel@vger.kernel.org;linux-security-module@vger.kernel.org From: Mimi Zohar To: linux-security-module , linux-ima-devel Cc: Dave Young , kexec@lists.infradead.org, linux-kernel@vger.kernel.org, Eric Biederman , Mimi Zohar Subject: [PATCH 1/3] ima: measure other types of data Date: Wed, 22 Jun 2016 09:35:03 -0400 X-Mailer: git-send-email 2.1.0 In-Reply-To: <1466602505-21915-1-git-send-email-zohar@linux.vnet.ibm.com> References: <1466602505-21915-1-git-send-email-zohar@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16062213-1617-0000-0000-00000130469A X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16062213-1618-0000-0000-0000462060A7 Message-Id: <1466602505-21915-2-git-send-email-zohar@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2016-06-22_09:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606220145 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In addition to files, other data (eg. boot command line) should be included in the measurement list to attest to the integrity of a running system. A new IMA hook named ima_buffer_check() calculates and includes the buffer hash in the measurement list. Callers of this hook provide the buffer, buffer length and a buffer identifier. Signed-off-by: Mimi Zohar --- include/linux/ima.h | 11 +++++ security/integrity/ima/Makefile | 2 +- security/integrity/ima/ima.h | 2 + security/integrity/ima/ima_buffer.c | 82 +++++++++++++++++++++++++++++++++++++ security/integrity/ima/ima_policy.c | 26 ++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 security/integrity/ima/ima_buffer.c diff --git a/include/linux/ima.h b/include/linux/ima.h index 0eb7c2e..01319b3 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -13,6 +13,10 @@ #include struct linux_binprm; +enum ima_buffer_id { + MEASURING_MAX_BUFFER_ID +}; + #ifdef CONFIG_IMA extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask, int opened); @@ -22,6 +26,8 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); extern void ima_post_path_mknod(struct dentry *dentry); +extern void ima_buffer_check(void *buf, loff_t size, + enum ima_buffer_id buffer_id); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -60,6 +66,11 @@ static inline void ima_post_path_mknod(struct dentry *dentry) return; } +static inline void ima_buffer_check(void *buf, loff_t size, + enum ima_buffer_id buffer_id) +{ + return; +} #endif /* CONFIG_IMA */ #ifdef CONFIG_IMA_APPRAISE diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile index 9aeaeda..c34599f 100644 --- a/security/integrity/ima/Makefile +++ b/security/integrity/ima/Makefile @@ -6,6 +6,6 @@ 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_buffer.o ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index db25f54..cc2e77b 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -154,6 +154,8 @@ enum ima_hooks { MAX_CHECK }; +int ima_match_buffer_id(enum ima_hooks func, int *pcr); + /* LIM API function definitions */ int ima_get_action(struct inode *inode, int mask, enum ima_hooks func, int *pcr); diff --git a/security/integrity/ima/ima_buffer.c b/security/integrity/ima/ima_buffer.c new file mode 100644 index 0000000..84c9494 --- /dev/null +++ b/security/integrity/ima/ima_buffer.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 IBM Corporation + * + * Author: + * Mimi Zohar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + */ +#include +#include +#include + +#include "ima.h" + +struct buffer_idmap { + enum ima_hooks func; + char *buf; +}; + +static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = { +}; + +static void process_buffer_measurement(void *buf, loff_t size, + enum ima_buffer_id buffer_id, int pcr) +{ + struct { + struct ima_digest_data hdr; + char digest[IMA_MAX_DIGEST_SIZE]; + } hash; + struct ima_template_entry *entry; + struct integrity_iint_cache tmp_iint, *iint = &tmp_iint; + struct ima_event_data event_data = {iint, NULL, NULL, NULL, 0, NULL}; + int violation = 0; + int result; + + memset(&hash, 0, sizeof(hash)); + hash.hdr.algo = ima_hash_algo; + result = ima_calc_buffer_hash(buf, size, &hash.hdr); + if (result < 0) { + pr_debug("failed calculating buffer hash\n"); + return; + } + + iint->ima_hash = &hash.hdr; + event_data.filename = _idmap[buffer_id].buf; + result = ima_alloc_init_template(&event_data, &entry); + if (result < 0) { + pr_debug("failed allocating template\n"); + return; + } + + result = ima_store_template(entry, violation, NULL, + event_data.filename, pcr); + if (result < 0) { + pr_debug("failed storing buffer measurement\n"); + ima_free_template_entry(entry); + } +} + +/** + * ima_buffer_check - based on policy, collect & store buffer measurement + * @buf: pointer to buffer + * @size: size of buffer + * @buffer_id: caller identifier + * + * Buffers can only be measured, not appraised. + */ +void ima_buffer_check(void *buf, loff_t size, enum ima_buffer_id buffer_id) +{ + int pcr = CONFIG_IMA_MEASURE_PCR_IDX; + + if (buffer_id > MEASURING_MAX_BUFFER_ID) + return; + + if (!ima_match_buffer_id(_idmap[buffer_id].func, &pcr)) + return; + + process_buffer_measurement(buf, size, buffer_id, pcr); +} +EXPORT_SYMBOL_GPL(ima_buffer_check); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index aed47b7..521d612 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -370,6 +370,32 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, return action; } +/** + * ima_match_buffer_id - decision based on policy + * @buffer_id: IMA buffer identifier + * + * Measure decision based the buffer identifier's existence in policy. + * Without an inode, buffers can only be measured, not appraised. + */ +int ima_match_buffer_id(enum ima_hooks func, int *pcr) +{ + struct ima_rule_entry *entry; + int result = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(entry, ima_rules, list) { + if ((entry->action == MEASURE) && (entry->flags & IMA_FUNC) && + (entry->func == func)) { + if (entry->flags & IMA_PCR) + *pcr = entry->pcr; + result = 1; + } + } + rcu_read_unlock(); + + return result; +} + /* * Initialize the ima_policy_flag variable based on the currently * loaded policy. Based on this flag, the decision to short circuit -- 2.1.0