linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] support other types of measurements
@ 2016-06-22 13:35 Mimi Zohar
  2016-06-22 13:35 ` [PATCH 1/3] ima: measure other types of data Mimi Zohar
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Mimi Zohar @ 2016-06-22 13:35 UTC (permalink / raw)
  To: linux-security-module, linux-ima-devel
  Cc: Dave Young, kexec, linux-kernel, Eric Biederman, Mimi Zohar

In addition to file measurements, other types of measurements should be
included in the IMA measurement list to attest to the integrity of the
running system.  This patch set introduces two new types of measurements -
buffer and pre-calculated digests.

The first, for example, can be used to measure the kexec boot command
line, while the latter could be used for including asymmetric key id
information.

Mimi Zohar (3):
  ima: measure other types of data
  kexec: measure boot command line
  ima: add pre-calculated measurements (experimental)

 Documentation/ABI/testing/ima_policy |   1 +
 include/linux/ima.h                  |  24 +++++
 kernel/kexec_file.c                  |   4 +
 security/integrity/ima/Kconfig       |   8 ++
 security/integrity/ima/Makefile      |   2 +-
 security/integrity/ima/ima.h         |   4 +
 security/integrity/ima/ima_buffer.c  | 164 +++++++++++++++++++++++++++++++++++
 security/integrity/ima/ima_policy.c  |  51 ++++++++++-
 8 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 security/integrity/ima/ima_buffer.c
-- 
2.1.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] ima: measure other types of data
  2016-06-22 13:35 [PATCH 0/3] support other types of measurements Mimi Zohar
@ 2016-06-22 13:35 ` Mimi Zohar
  2016-06-22 13:35 ` [PATCH 2/3] kexec: measure boot command line Mimi Zohar
  2016-06-22 13:35 ` [PATCH 3/3] ima: add pre-calculated measurements (experimental) Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2016-06-22 13:35 UTC (permalink / raw)
  To: linux-security-module, linux-ima-devel
  Cc: Dave Young, kexec, linux-kernel, Eric Biederman, Mimi Zohar

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 <zohar@linux.vnet.ibm.com>
---
 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 <linux/fs.h>
 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 <zohar@us.ibm.com>
+ *
+ * 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 <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/ima.h>
+
+#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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] kexec: measure boot command line
  2016-06-22 13:35 [PATCH 0/3] support other types of measurements Mimi Zohar
  2016-06-22 13:35 ` [PATCH 1/3] ima: measure other types of data Mimi Zohar
@ 2016-06-22 13:35 ` Mimi Zohar
  2016-06-22 13:35 ` [PATCH 3/3] ima: add pre-calculated measurements (experimental) Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2016-06-22 13:35 UTC (permalink / raw)
  To: linux-security-module, linux-ima-devel
  Cc: Dave Young, kexec, linux-kernel, Eric Biederman, Mimi Zohar

This patch defines the buffer identifier "KEXEC_CMDLINE_CHECK" for
measuring the boot command line.

eg: echo -n -e `cat /proc/cmdline | sed 's/^.*root=/root=/'` | sha256sum

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy | 1 +
 include/linux/ima.h                  | 1 +
 kernel/kexec_file.c                  | 4 ++++
 security/integrity/ima/ima.h         | 1 +
 security/integrity/ima/ima_buffer.c  | 2 ++
 security/integrity/ima/ima_policy.c  | 9 ++++++++-
 6 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index bb0f9a1..5a99c6f 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -28,6 +28,7 @@ Description:
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
+				[KEXEC_CMDLINE_CHECK]
 			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
 			       [[^]MAY_EXEC]
 			fsmagic:= hex value
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 01319b3..88203f9 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -14,6 +14,7 @@
 struct linux_binprm;
 
 enum ima_buffer_id {
+	MEASURING_KEXEC_CMDLINE,
 	MEASURING_MAX_BUFFER_ID
 };
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 503bc2d..acc8dad1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/fs.h>
+#include <linux/ima.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <linux/syscalls.h>
@@ -178,6 +179,9 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
 			ret = -EINVAL;
 			goto out;
 		}
+
+		ima_buffer_check(image->cmdline_buf, cmdline_len - 1,
+				 MEASURING_KEXEC_CMDLINE);
 	}
 
 	/* Call arch image load handlers */
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index cc2e77b..5f21a9a 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -150,6 +150,7 @@ enum ima_hooks {
 	FIRMWARE_CHECK,
 	KEXEC_KERNEL_CHECK,
 	KEXEC_INITRAMFS_CHECK,
+	KEXEC_CMDLINE_CHECK,
 	POLICY_CHECK,
 	MAX_CHECK
 };
diff --git a/security/integrity/ima/ima_buffer.c b/security/integrity/ima/ima_buffer.c
index 84c9494..e74131b 100644
--- a/security/integrity/ima/ima_buffer.c
+++ b/security/integrity/ima/ima_buffer.c
@@ -20,6 +20,8 @@ struct buffer_idmap {
 };
 
 static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = {
+	[MEASURING_KEXEC_CMDLINE].func = KEXEC_CMDLINE_CHECK,
+	[MEASURING_KEXEC_CMDLINE].buf = "boot-cmdline",
 };
 
 static void process_buffer_measurement(void *buf, loff_t size,
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 521d612..8e53f84 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -663,6 +663,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
 				 == 0)
 				entry->func = KEXEC_INITRAMFS_CHECK;
+			else if (strcmp(args[0].from, "KEXEC_CMDLINE_CHECK")
+				 == 0)
+				entry->func = KEXEC_CMDLINE_CHECK;
 			else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
 				entry->func = POLICY_CHECK;
 			else
@@ -926,7 +929,7 @@ enum {
 	func_file = 0, func_mmap, func_bprm,
 	func_module, func_firmware, func_post,
 	func_kexec_kernel, func_kexec_initramfs,
-	func_policy
+	func_kexec_cmdline, func_policy
 };
 
 static char *func_tokens[] = {
@@ -938,6 +941,7 @@ static char *func_tokens[] = {
 	"POST_SETATTR",
 	"KEXEC_KERNEL_CHECK",
 	"KEXEC_INITRAMFS_CHECK",
+	"KEXEC_CMDLINE_CHECK",
 	"POLICY_CHECK"
 };
 
@@ -1009,6 +1013,9 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
 	case KEXEC_INITRAMFS_CHECK:
 		seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
 		break;
+	case KEXEC_CMDLINE_CHECK:
+		seq_printf(m, pt(Opt_func), ft(func_kexec_cmdline));
+		break;
 	case POLICY_CHECK:
 		seq_printf(m, pt(Opt_func), ft(func_policy));
 		break;
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] ima: add pre-calculated measurements (experimental)
  2016-06-22 13:35 [PATCH 0/3] support other types of measurements Mimi Zohar
  2016-06-22 13:35 ` [PATCH 1/3] ima: measure other types of data Mimi Zohar
  2016-06-22 13:35 ` [PATCH 2/3] kexec: measure boot command line Mimi Zohar
@ 2016-06-22 13:35 ` Mimi Zohar
  2 siblings, 0 replies; 4+ messages in thread
From: Mimi Zohar @ 2016-06-22 13:35 UTC (permalink / raw)
  To: linux-security-module, linux-ima-devel
  Cc: Dave Young, kexec, linux-kernel, Eric Biederman, Mimi Zohar

This patch defines a new IMA hook named ima_add_measurement_check()
for including pre-calculated measurements in the IMA measurement list.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy |   2 +-
 include/linux/ima.h                  |  12 ++++
 security/integrity/ima/Kconfig       |   8 +++
 security/integrity/ima/ima.h         |   1 +
 security/integrity/ima/ima_buffer.c  | 116 +++++++++++++++++++++++++++++------
 security/integrity/ima/ima_policy.c  |  18 +++++-
 6 files changed, 136 insertions(+), 21 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 5a99c6f..e5a137e 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -28,7 +28,7 @@ Description:
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
-				[KEXEC_CMDLINE_CHECK]
+				[KEXEC_CMDLINE_CHECK] [PRECALC_CHECK]
 			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
 			       [[^]MAY_EXEC]
 			fsmagic:= hex value
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 88203f9..797de51 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -15,6 +15,7 @@ struct linux_binprm;
 
 enum ima_buffer_id {
 	MEASURING_KEXEC_CMDLINE,
+	MEASURING_PRECALC_DATA,
 	MEASURING_MAX_BUFFER_ID
 };
 
@@ -29,6 +30,9 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
 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);
+extern void ima_add_measurement_check(const char *hashname, u8 *digest,
+				      loff_t size, enum ima_buffer_id buffer_id,
+				      char *hint);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -72,6 +76,14 @@ static inline void ima_buffer_check(void *buf, loff_t size,
 {
 	return;
 }
+
+static inline void ima_add_measurement_check(const char *hashname, u8 *digest,
+					     loff_t size,
+					     enum ima_buffer_id buffer_id,
+					     char *hint)
+{
+	return;
+}
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 5487827..0fb54d3 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -44,6 +44,14 @@ config IMA_LSM_RULES
 	help
 	  Disabling this option will disregard LSM based policy rules.
 
+config IMA_PRECALC_RULES
+	bool "Permit pre-calculated measurements (EXPERIMENTAL)"
+	depends on IMA
+	default n
+	help
+	  Enabling this option will permit pre-calculated measurements
+	  to be added to the IMA measurement list.
+
 choice
 	prompt "Default template"
 	default IMA_NG_TEMPLATE
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 5f21a9a..ccad21d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -152,6 +152,7 @@ enum ima_hooks {
 	KEXEC_INITRAMFS_CHECK,
 	KEXEC_CMDLINE_CHECK,
 	POLICY_CHECK,
+	PRECALC_CHECK,
 	MAX_CHECK
 };
 
diff --git a/security/integrity/ima/ima_buffer.c b/security/integrity/ima/ima_buffer.c
index e74131b..ad49f6c 100644
--- a/security/integrity/ima/ima_buffer.c
+++ b/security/integrity/ima/ima_buffer.c
@@ -11,6 +11,8 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ima.h>
+#include <crypto/hash_info.h>
+#include <linux/string_helpers.h>
 
 #include "ima.h"
 
@@ -21,9 +23,37 @@ struct buffer_idmap {
 
 static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = {
 	[MEASURING_KEXEC_CMDLINE].func = KEXEC_CMDLINE_CHECK,
-	[MEASURING_KEXEC_CMDLINE].buf = "boot-cmdline",
+	[MEASURING_KEXEC_CMDLINE].buf = "kexec-boot-cmdline",
+	[MEASURING_PRECALC_DATA].func = PRECALC_CHECK,
+	[MEASURING_PRECALC_DATA].buf = "precalc",
 };
 
+#define IMA_MAX_BUFFER_HINT_SIZE 255
+
+static int store_buffer_measurement(struct ima_digest_data *hash, int pcr,
+				    char *buffer_hint)
+{
+	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;
+
+	iint->ima_hash = hash;
+	event_data.filename = buffer_hint;
+
+	result = ima_alloc_init_template(&event_data, &entry);
+	if (result < 0)
+		return result;
+
+	result = ima_store_template(entry, violation, NULL,
+				    event_data.filename, pcr);
+	if (result < 0)
+		ima_free_template_entry(entry);
+
+	return result;
+}
+
 static void process_buffer_measurement(void *buf, loff_t size,
 				       enum ima_buffer_id buffer_id, int pcr)
 {
@@ -31,10 +61,6 @@ static void process_buffer_measurement(void *buf, loff_t size,
 		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));
@@ -45,20 +71,10 @@ static void process_buffer_measurement(void *buf, loff_t size,
 		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) {
+	result = store_buffer_measurement(&hash.hdr, pcr,
+					  _idmap[buffer_id].buf);
+	if (result < 0)
 		pr_debug("failed storing buffer measurement\n");
-		ima_free_template_entry(entry);
-	}
 }
 
 /**
@@ -82,3 +98,67 @@ void ima_buffer_check(void *buf, loff_t size, enum ima_buffer_id buffer_id)
 	process_buffer_measurement(buf, size, buffer_id, pcr);
 }
 EXPORT_SYMBOL_GPL(ima_buffer_check);
+
+/**
+ * ima_add_measurement_check - add pre-calculated hash measurement
+ * @hashname: pointer to hash algorithm name
+ * @digest: pointer to hash digest
+ * @size: hash digest size
+ * @buffer_id: caller identifier
+ * @hint: measurement identifier
+ *
+ * Include pre-calculated hash measurements in the IMA measurement list.
+ */
+void ima_add_measurement_check(const char *hashname, u8 *digest, loff_t size,
+			      enum ima_buffer_id buffer_id, char *hint)
+{
+	struct {
+		struct ima_digest_data hdr;
+		char digest[IMA_MAX_DIGEST_SIZE];
+	} hash;
+	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+	char buffer_hint[IMA_MAX_BUFFER_HINT_SIZE];
+	char *buf;
+	int result, i;
+
+	if (buffer_id > MEASURING_MAX_BUFFER_ID)
+		return;
+
+	if (!ima_match_buffer_id(_idmap[buffer_id].func, &pcr))
+		return;
+
+	if (!hint) {
+		pr_debug("missing buffer hint\n");
+		return;
+	}
+
+	buf = kstrdup_quotable(hint, GFP_KERNEL);
+	if (!buf) {
+		pr_debug("failed quoting buffer hint\n");
+		return;
+	}
+
+	/* Limit the total measurement hint to IMA_MAX_BUFFER_HINT_SIZE. */
+	snprintf(buffer_hint, sizeof(buffer_hint), "(%s) %s",
+		 _idmap[buffer_id].buf, buf);
+	kfree(buf);
+
+	memset(&hash, 0, sizeof(hash));
+	for (i = 1; i < HASH_ALGO__LAST; i++) {
+		if (strcmp(hashname, hash_algo_name[i]) != 0)
+			continue;
+		hash.hdr.algo = i;
+		break;
+	}
+	if (hash.hdr.algo == 0) {
+		pr_debug("invalid hash algorithm (%d)\n", hash.hdr.algo);
+		return;
+	}
+
+	hash.hdr.length = size;
+	memcpy(&hash.hdr.digest, digest, size);
+	result = store_buffer_measurement(&hash.hdr, pcr, buffer_hint);
+	if (result < 0)
+		pr_debug("failed to store buffer measurement\n");
+}
+EXPORT_SYMBOL_GPL(ima_add_measurement_check);
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 8e53f84..4094dd7 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -20,6 +20,7 @@
 #include <linux/rculist.h>
 #include <linux/genhd.h>
 #include <linux/seq_file.h>
+#include <linux/ima.h>
 
 #include "ima.h"
 
@@ -54,6 +55,12 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+#ifdef CONFIG_MEASURING_PRECALC_RULES
+static int permit_measuring_precalc_rules = 1;
+#else
+static int permit_measuring_precalc_rules;
+#endif
+
 struct ima_rule_entry {
 	struct list_head list;
 	int action;
@@ -668,6 +675,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 				entry->func = KEXEC_CMDLINE_CHECK;
 			else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
 				entry->func = POLICY_CHECK;
+			else if ((strcmp(args[0].from, "PRECALC_CHECK") == 0)
+				 && permit_measuring_precalc_rules)
+				entry->func = PRECALC_CHECK;
 			else
 				result = -EINVAL;
 			if (!result)
@@ -929,7 +939,7 @@ enum {
 	func_file = 0, func_mmap, func_bprm,
 	func_module, func_firmware, func_post,
 	func_kexec_kernel, func_kexec_initramfs,
-	func_kexec_cmdline, func_policy
+	func_kexec_cmdline, func_policy, func_precalc
 };
 
 static char *func_tokens[] = {
@@ -942,7 +952,8 @@ static char *func_tokens[] = {
 	"KEXEC_KERNEL_CHECK",
 	"KEXEC_INITRAMFS_CHECK",
 	"KEXEC_CMDLINE_CHECK",
-	"POLICY_CHECK"
+	"POLICY_CHECK",
+	"PRECALC_CHECK"
 };
 
 void *ima_policy_start(struct seq_file *m, loff_t *pos)
@@ -1019,6 +1030,9 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
 	case POLICY_CHECK:
 		seq_printf(m, pt(Opt_func), ft(func_policy));
 		break;
+	case PRECALC_CHECK:
+		seq_printf(m, pt(Opt_func), ft(func_precalc));
+		break;
 	default:
 		snprintf(tbuf, sizeof(tbuf), "%d", func);
 		seq_printf(m, pt(Opt_func), tbuf);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-06-22 13:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22 13:35 [PATCH 0/3] support other types of measurements Mimi Zohar
2016-06-22 13:35 ` [PATCH 1/3] ima: measure other types of data Mimi Zohar
2016-06-22 13:35 ` [PATCH 2/3] kexec: measure boot command line Mimi Zohar
2016-06-22 13:35 ` [PATCH 3/3] ima: add pre-calculated measurements (experimental) Mimi Zohar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).