Skip to contentSkip to conversation

integrity: IMA as an integrity service provider

RFC PATCH In review Mimi Zohar 2 participants 3 messages May 21, 2008 – May 22, 2008

Subsystems (4)
lore
Share & tools
lore

Mimi Zohar

author
#0 lore raw

RFC PATCH 4/4 integrity: IMA as an integrity service provider

This is a re-release of Integrity Measurement Architecture(IMA) as an independent Linunx Integrity Module(LIM) service provider, which implements the new LIM must_measure(), collect_measurement(), store_measurement(), and display_template() API calls. The store_measurement() call supports two types of data, IMA (i.e. file data) and generic template data.

When store_measurement() is called for the IMA type of data, the file measurement and the file name hint are used to form an IMA template. IMA then calculates the IMA template measurement(hash) and submits it to the TPM chip for inclusion in one of the chip's Platform Configuration Registers (PCR).

When store_measurement() is called for generic template data, IMA calculates the measurement(hash) of the template data, and submits the template measurement to the TPM chip for inclusion in one of the chip's Platform Configuration Registers(PCR).

In order to view the contents of template data through securityfs, the template_display() function must be defined in the registered template_operations. In the case of the IMA template, the list of file names and files hashes submitted can be viewed through securityfs.

IMA can be included or excluded in the kernel configuration. If included in the kernel and the IMA_BOOTPARAM is selected, IMA can also be enabled/disabled on the kernel command line with 'ima='.

---

security/integrity/ima/Kconfig new file +68 -0
Index: linux-2.6.26-rc3-git2/security/integrity/ima/Kconfig
===================================================================
@@ -0,0 +1,68 @@
+#
+# IBM Integrity Measurement Architecture
+#
+
+config IMA_MEASURE
+	bool "TCG run-time Integrity Measurement Architecture(IMA)"
+	depends on INTEGRITY
+	depends on ACPI
+	select CRYPTO
+	select CRYPTO_HMAC
+	select CRYPTO_MD5
+	select CRYPTO_SHA1
+	select TCG_TPM
+	help
+	  IMA maintains a list of hash values of executables and
+	  other sensitive system files loaded into the run-time
+	  of this system. If your system has a TPM chip, then IMA
+	  also maintains an aggregate integrity value over this
+	  list inside the TPM hardware.  These measurements and
+	  the aggregate (signed inside the TPM) can be retrieved
+	  and presented to remote parties to establish system
+	  properties. If unsure, say N.
+
+config IMA_BOOTPARAM
+	bool "IMA boot parameter"
+	depends on IMA_MEASURE
+	default n
+	help
+	  This option adds a kernel parameter 'ima', which allows IMA
+	  to be disabled at boot.  If this option is selected, IMA
+	  functionality can be disabled with ima=0 on the kernel
+	  command line.  The purpose of this option is to allow a single
+	  kernel image to be distributed with IMA built in, but not
+	  necessarily enabled.
+
+	  If you are unsure how to answer this question, answer N.
+
+config IMA_BOOTPARAM_VALUE
+	int "IMA boot parameter default value"
+	depends on IMA_BOOTPARAM
+	range 0 1
+	default 0
+	help
+	  This option sets the default value for the kernel parameter
+	  'ima=', which allows IMA to be disabled at boot.  If this
+	  option is set to 0 (zero), the IMA kernel parameter will
+	  default to 0, disabling IMA at bootup.  If this option is
+	  set to 1 (one), the IMA kernel parameter will default to 1,
+	  enabling IMA at bootup.
+
+	  If you are unsure how to answer this question, answer 0.
+
+config IMA_MEASURE_PCR_IDX
+	int "PCR for Aggregate (8<= Index <= 14)"
+	depends on IMA_MEASURE
+	range 8 14
+	default 10
+	help
+	  IMA_MEASURE_PCR_IDX determines the TPM PCR register index
+	  that IMA uses to maintain the integrity aggregate of the
+	  measurement list.  If unsure, use the default 10.
+
+config IMA_BASE_HOOKS
+	bool "IMA base hooks"
+	depends on IMA_MEASURE
+	default n
+	help
+	  Enable this option to allow the LSM module to enforce integrity.
security/integrity/ima/Makefile new file +6 -0
Index: linux-2.6.26-rc3-git2/security/integrity/ima/Makefile
===================================================================
@@ -0,0 +1,6 @@
+
+obj-$(CONFIG_IMA_MEASURE) += ima.o
+
+ifeq ($(CONFIG_IMA_MEASURE), y)
+ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o
+endif
security/integrity/ima/ima.h new file +137 -0

137 lines not on this page · raw message

security/integrity/ima/ima_crypto.c new file +170 -0

170 lines not on this page · raw message

security/integrity/ima/ima_fs.c new file +437 -0

437 lines not on this page · raw message

security/integrity/ima/ima_init.c new file +103 -0

103 lines not on this page · raw message

security/integrity/ima/ima_main.c new file +418 -0

418 lines not on this page · raw message

security/integrity/ima/ima_queue.c new file +125 -0

125 lines not on this page · raw message

Documentation/kernel-parameters.txt +12 -0
Index: linux-2.6.26-rc3-git2/Documentation/kernel-parameters.txt
===================================================================
@@ -44,6 +44,7 @@ parameter is applicable:
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
 	IA-64	IA-64 architecture is enabled.
+	IMA	Integrity measurement architecture is enabled.
 	IOSCHED	More than one I/O scheduler is enabled.
 	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
 	ISAPNP	ISA PnP code is enabled.
@@ -804,6 +805,17 @@ and is between 256 and 4096 characters. 
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
 
+	ima=		[IMA] Disable or enable IMA at boot time.
+			Format: { "0" | "1" }
+			See security/ima/Kconfig help text.
+			0 -- disable.
+			1 -- enable.
+			Default value is set via kernel config option.
+
+	ima_hash=	[IMA] runtime ability to define hash crypto alg.
+			Format: { "MD5" | "SHA1" }
+			Default is "SHA1".
+
 	in2000=		[HW,SCSI]
 			See header of drivers/scsi/in2000.c.
 
security/integrity/Kconfig +2 -3
Index: linux-2.6.26-rc3-git2/security/integrity/Kconfig
===================================================================
@@ -2,8 +2,6 @@
 # Integrity configuration
 #
 
-menu "Integrity options"
-
 config INTEGRITY
 	bool "Enable different integrity models"
 	help
@@ -21,4 +19,5 @@ config INTEGRITY_AUDIT
 	  allows integrity auditing to be disabled at boot.  If this
 	  option is selected, integrity auditing can be disabled with
 	  'integrity_audit=0' on the kernel command line.
-endmenu
+
+source security/integrity/ima/Kconfig
security/integrity/Makefile +2 -0
Index: linux-2.6.26-rc3-git2/security/integrity/Makefile
===================================================================
@@ -5,3 +5,5 @@
 # Object file lists
 obj-$(CONFIG_INTEGRITY)			+= integrity.o integrity_dummy.o \
 					integrity_audit.o integrity_policy.o
+
+obj-$(CONFIG_IMA_MEASURE)		+= ima/
include/linux/ima.h new file +48 -0

48 lines not on this page · raw message

security/integrity/ima/ima_api.c new file +362 -0

362 lines not on this page · raw message

maintainer
#1 lore raw

security/integrity/ima/ima.h line 43

Quoted 2 lines · Mimi Zohar
security/integrity/ima/ima.h new file +2 -0
+#define IMA_HASH_KEY(digest) (hash_long(\
+	(unsigned long)(*digest), IMA_HASH_BITS));

Please make this a static inline and use hash_ptr().

security/integrity/ima/ima_crypto.c line 79

Quoted 7 lines
security/integrity/ima/ima_crypto.c new file +7 -0
+	i_size = i_size_read(file->f_dentry->d_inode);
+	while (offset < i_size) {
+		int error;
+
+		rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
+		if (rbuf_len <= 0)
+			break;

Why is the return value of kernel_read() not being propagated to the caller?

security/integrity/ima/ima_crypto.c line 87

Quoted 5 lines
security/integrity/ima/ima_crypto.c new file +5 -0
+		error = crypto_hash_update(desc, sg, rbuf_len);
+		if (error) {
+			result = -EINVAL;
+			break;
+		}

Why are you replacing the error code from crypto_hash_update() with -EINVAL ?

security/integrity/ima/ima_crypto.c line 115

Quoted 6 lines
security/integrity/ima/ima_crypto.c new file +6 -0
+	tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		printk(KERN_INFO "%s: failed to load %s transform: %ld\n",
+		       __func__, ima_hash, PTR_ERR(tfm));
+		return -ENOSYS;
+	}

Similarly, why not propagate the actual error ?

(This kind of thing happens quite a lot in the code).

Quoted 7 lines
security/integrity/ima/ima_main.c new file +7 -0
+static int __init init_ima(void)
+{
+	int error;
+	tfm_hash = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+
+	error = ima_init();
+	if (error)

security/integrity/ima/ima_main.c line 405

Quoted 10 lines
security/integrity/ima/ima_main.c new file +10 -0
+		goto out;
+	ima_fixup_inodes();
+	if (ima_base_hooks)
+		error = register_integrity(&ima_base_ops);
+	else
+		error = register_integrity(&ima_integrity_ops);
+	register_template("ima", &ima_template_ops);
+out:
+	return error;
+}

What if crypto_alloc_hash() fails ? Actually, where is it used?

- James

Signature · 2 lines
James Morris
<[email protected]>
author
#2 lore raw

Thank you for reviewing the code. Will fix these and add locking around integrity_templates.

Mimi

Quoted 62 lines · James Morris

security/integrity/ima/ima.h line 43

Quoted 2 lines · Mimi Zohar
security/integrity/ima/ima.h new file +2 -0
+#define IMA_HASH_KEY(digest) (hash_long(\
+	(unsigned long)(*digest), IMA_HASH_BITS));

Please make this a static inline and use hash_ptr().

security/integrity/ima/ima_crypto.c line 79

Quoted 7 lines
security/integrity/ima/ima_crypto.c new file +7 -0
+	i_size = i_size_read(file->f_dentry->d_inode);
+	while (offset < i_size) {
+		int error;
+
+		rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
+		if (rbuf_len <= 0)
+			break;

Why is the return value of kernel_read() not being propagated to the caller?

security/integrity/ima/ima_crypto.c line 87

Quoted 5 lines
security/integrity/ima/ima_crypto.c new file +5 -0
+		error = crypto_hash_update(desc, sg, rbuf_len);
+		if (error) {
+			result = -EINVAL;
+			break;
+		}

Why are you replacing the error code from crypto_hash_update() with -EINVAL ?

security/integrity/ima/ima_crypto.c line 115

Quoted 6 lines
security/integrity/ima/ima_crypto.c new file +6 -0
+	tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		printk(KERN_INFO "%s: failed to load %s transform: %ld\n",
+		       __func__, ima_hash, PTR_ERR(tfm));
+		return -ENOSYS;
+	}

Similarly, why not propagate the actual error ?

(This kind of thing happens quite a lot in the code).

Quoted 7 lines
security/integrity/ima/ima_main.c new file +7 -0
+static int __init init_ima(void)
+{
+	int error;
+	tfm_hash = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+
+	error = ima_init();
+	if (error)

security/integrity/ima/ima_main.c line 405

Quoted 10 lines
security/integrity/ima/ima_main.c new file +10 -0
+		goto out;
+	ima_fixup_inodes();
+	if (ima_base_hooks)
+		error = register_integrity(&ima_base_ops);
+	else
+		error = register_integrity(&ima_integrity_ops);
+	register_template("ima", &ima_template_ops);
+out:
+	return error;
+}

What if crypto_alloc_hash() fails ? Actually, where is it used?

- James