Re: [RFC][Patch 5/5]integrity: IMA as an integrity service provider

Previous thread: [RFC][PATCH 4/5]integrity: Linux Integrity Module(LIM) by Mimi Zohar on Friday, May 23, 2008 - 8:05 am. (6 messages)

Next thread: [PATCH] remove debug printk from DRM suspend path by Jesse Barnes on Friday, May 23, 2008 - 8:40 am. (1 message)
From: Mimi Zohar
Date: Friday, May 23, 2008 - 8:05 am

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='.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
Index: linux-2.6.26-rc3-git2/security/integrity/ima/Kconfig
===================================================================
--- /dev/null
+++ 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
+	  ...
From: Randy Dunlap
Date: Friday, May 23, 2008 - 4:30 pm

kernel-doc notation first line (short description) cannot be continued















---
~Randy
--

From: Mimi Zohar
Date: Monday, May 26, 2008 - 6:02 pm

TCG stands for Trusted Computing Group.
(https://www.trustedcomputinggroup.org/faq/)

Thank you for reviewing the code. I'll make the kernel doc, Kconfig
and Makefile changes and repost.

Mimi



--

From: Mimi Zohar
Date: Tuesday, May 27, 2008 - 7:36 am

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='.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
Index: linux-2.6.26-rc3-git2/security/integrity/ima/Kconfig
===================================================================
--- /dev/null
+++ linux-2.6.26-rc3-git2/security/integrity/ima/Kconfig
@@ -0,0 +1,69 @@
+#
+# IBM Integrity Measurement Architecture
+#
+
+config IMA_MEASURE
+	bool "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
+	  The Trusted Computing Group(TCG) runtime Integrity
+	  Measurement ...
From: Randy Dunlap
Date: Wednesday, June 11, 2008 - 3:31 pm

Thanks.
---
~Randy
--

From: Andrew Morton
Date: Wednesday, May 28, 2008 - 1:22 am

- I see lots of user file I/O being done from within the kernel. 
  This makes eyebrows raise.  Also some other eyebrow-raising
  file-related things in there.

- A complicated-looking in-kernel string parser which is implementing
  an new and apparently-undocumented user->kernel ABI.

- Some GFP_ATOMICs which can hopefully become GFP_KERNEL.

- timespec_set() is unneeeded - just use struct assignment (ie: "=")

- timespec_recent() looks a bit hacky.  The problems which are being
  solved here should be described in the changelog.  Perhaps we can
  think of a better way, but first we have to know about it.

- shouldn't ima_inode_init() initialise tv_usec too?

- All the games with mtimes should be described in the changelog too.

- All the `static struct integrity_operations' instances could be
  made const.  And lots of other foo_operations too, I expect.

  That will lead to a constification chase all over the place, but
  it's probably for the best.  This is after all a "security" feature
  and there is perhaps some benefit in getting your eminently
  hijackable function pointers into read-only memory.

- ima_fixup_inodes looks like it will race and crash against a
  well-timed unmount.  I expect you will need to bump s_count before
  dropping sb_lock.  See writeback_inodes() for an example.

- bug: ima_fixup_inodes() does a GFP_KERNEL allocation inside
  inode->i_lock.  This bug shouldn't have got this far.  Please always
  enable all kernel debugging features when testing code. 
  Documentation/SubmitChecklist has useful things.

- inode.i_lock is defined as an innermost lock which is used for
  protecting data internal to the inode.  You appear to be using it for
  way too much stuff in here.

- It would be useful to add a comment explaining why
  late_initcall(init_ima) is using late_initcall() rather than plain
  old module_init().  Because it is impossible for the reader to
  determine this information from the implementation.

- ...
From: Mimi Zohar
Date: Wednesday, May 28, 2008 - 8:17 pm

The amount of I/O is dependent on the number of files being measured.
The default policy measures a whole lot.  An LSM specific integrity 
policy would cut down on the number of files being measured. For now,
either remove the third rule in default_rules or replace the default
rules with a new policy. To load a new policy execute:
	./integrity_load < policy

policy:
#
# Integrity measure policy
#
func=BPRM_CHECK 
func=FILE_MMAP mask=MAY_EXEC
#func=INODE_PERMISSION mask=MAY_READ

integrity_load.c:
/* 
 * integrity_load.c 
 *
 * Strip comments from integrity measurement policy file and load 
 * policy rules into the kernel by writing to security/ima/policy.
 *
 */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	int fd;
	char *policyname = "/sys/kernel/security/ima/policy";
	char *line = NULL;
	ssize_t len = 0, readcnt;
	int rc = 0;

	if (argc == 2)
		policyname = argv[1];

	fd = open(policyname, O_WRONLY);
	if (fd == -1) {
		perror("opening policy");
		exit(EXIT_FAILURE);
	}
	while ((readcnt = getline(&line, &len, stdin)) != -1) {
		if (*line == '#')
			continue;
		printf("%s", line);
		rc = write(fd, line, readcnt);
		if (rc == -1) {
			perror("write");
			break;
		}
	}

	close(fd);
	if (line)
		free(line);
	return (rc == -1) ? EXIT_FAILURE : EXIT_SUCCESS;


Am confused.  timespec_set is doing an assignment. Should I


I don't think it matters.  timespec_equal checks that the mtime in
the iint and inode are the same.  If they are the same then we don't
need to recalculate the hash, unless it's been updated in really

Ok. The timespec_recent and mtime issues are part of the same problem









Yes, one solution is to add policy support so that rules could be 
defined instead of actually hard coding each and every fs magic 

Ok.

--

From: Andrew Morton
Date: Wednesday, May 28, 2008 - 8:30 pm

The problem is that the code is doing in-kernel user file I/O *at all*.
It's a red flag.

Look who else is using kernel_read(): just the exec code.  Plus

	struct timespec a, b;



What is "initialisation"?  During initcalls?  Are there even any files
in cache at that time?  I bet we can arrange for the answer to become
"no".


--

From: Mimi Zohar
Date: Thursday, May 29, 2008 - 2:50 pm

i_version is now working on my system.  It looks good. Is
there anything that I need to be concerned about, such as
limited filesystem support or the i_version is not updated 
by file_close for mmaped files?

Thanks!

Mimi

--

From: Andrew Morton
Date: Thursday, May 29, 2008 - 4:35 pm

On Thu, 29 May 2008 17:50:34 -0400


erk, I'm not an i_version person.  It seems that it's only used on
directories (to patch up readdir coherency problems) so I guess I
misled you there.

There's file_struct.f_version, which is no good.

i_generation is no good either.

We've documented these things so wonderfully!

i_writecount looks good?
--

From: Mimi Zohar
Date: Thursday, May 29, 2008 - 6:58 pm

No, no.  Initially, that's what I thought. I finally found
file_update_time() calls inode_inc_iversion(), which updates 
the i_version.  So, it does work.  The question is whether

--

From: Andrew Morton
Date: Thursday, May 29, 2008 - 7:04 pm

OK.

Before 2.6.17 it wouldn't have worked much at all on MAP_SHARED
modifications.

After 2.6.17 things will be better - we update the mtime on the
clean->dirty transitions of a page.  So the first modification after an
mmap will update the time.

Subsequent modifications via the mmap will not update the file time. 
Until something (usually pdflush) writes the page out.  Then the next
modification via mmap will cause another clean->dirty transition on the
page, hence another mtime update.

So there's a by-default 30-odd second uncertainty with MAP_SHARED
alterations.

--

From: Mimi Zohar
Date: Friday, May 30, 2008 - 6:06 am

Yes, during the initcalls.  Is this possible even when using
late_initcall().  IMA is dependent on the TPM being available,
if it is being used.

Mimi



--

From: Mimi Zohar
Date: Wednesday, May 28, 2008 - 8:33 pm

This is one of the five integrity API calls.  Each integrity template 

ima_collect_measurement is also one of the five integrity API calls.

Here is a sample template kernel module that measures kernel memory.
Of the five integrity API calls, it implements 
integrity_collect_measurement(), integrity_store_measurement(), and
integrity_display_measurement(). It collects and stores measurements
based on data read from security/kmem-template. The format is 
"name length address".  The name can be any string identifier such as
"proc_root"; the length is the number of bytes to measure; and address
is a kernel memory address, which can be looked up in /proc/kallsyms.
One caveat, the sample program currently does not validate the address.  
A userspace application triggers the measurement by writing to 
security/kmem-template.

/* 
 * Copyright (C) 2008 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.
 *
 * kmem-template.c
 * 	- defines a kernel memory template
 * 	- reads from security/kmem-template "name length address"
 * 	- collects and stores measurement from address for length bytes
 */

#include <asm/uaccess.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/notifier.h>
#include <linux/security.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
#include <linux/security.h>
#include <linux/integrity.h>
#include <linux/ima.h>

#define MY_NAME THIS_MODULE->name
#define IMA_DIGEST_SIZE		20

static int __init init_kmem_template(void);
static void __exit cleanup_kmem_template(void);

struct kmem_data {
	char name[25];
	char *buf;
	int ...
From: Pavel Machek
Date: Saturday, May 31, 2008 - 12:54 am

...also, it would be nice to see explanation 'what is this good for'.

Closest explanation I remember was 'it will protect you by making
system unbootable if someone stole disk with your /usr filesystem --
but not / filesystem -- added some rootkit, and then stealthily
returned it'. That seems a) very unlikely scenario and b) probably
better solved by encrypting /usr.
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--

From: david safford
Date: Tuesday, June 24, 2008 - 9:28 am

Sorry about this delayed response - we are about to repost for RFC, and
noticed we missed responding to this.

You are thinking about a related project, EVM, which HMAC's a file's
metadata, to protect against off-line attacks, (which admittedly
many users are not concerned about.)

This submission, IMA, provides hardware (TPM) based measurement and
attestation, which measures all files before they are accessed in
any way (on the inode_permission, bprm and mmap hooks), and
commits the measurements to the TPM. The TPM can sign these 
measurement lists, and thus the system can prove to itself and
to a third party these measurements in a way that cannot be
circumvented by malicious or compromised software. IMA is just one
part of integrity detection, as it does not detect purely in-memory
attacks, such as worms. 

dave safford
--

From: Pavel Machek
Date: Tuesday, August 5, 2008 - 10:35 am

And proofing to third party is useful for what....? Given that it can
be worked around by modifying files in memory, or by special
hardware...? Disney?

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--

From: david safford
Date: Tuesday, June 24, 2008 - 9:28 am

Sorry about this delayed response - we are about to repost for RFC, and
noticed we missed responding to this.

The Trusted Computing (TPM) model requires that all files be measured,
(hashed) and the measurement committed to the hardware TPM before any
data of the file is accessed in any way. In addition, if the measurement
is incorrect, all access to the file must be denied. 

This requirement parallels the LSM mandatory access control decisions
in the inode_permission, bprm, and mmap hooks, and naturally leads to 
IMA hooks in the same locations, with similar functionality, but with
the addition of hashing the data. The code would have to significantly
more complex to do the hashing at these points through userspace.

In addition, doing the hashing in userspace gives significantly poorer
performance. With in-kernel hashing, at boot time, we typically measure
some six thousand files with less than 10% (5 seconds) overhead, which
is acceptable to most users. Anything much slower can be annoying enough
that users will turn the measurement off.

dave safford
--

From: Pavel Machek
Date: Tuesday, August 5, 2008 - 10:32 am

TPM model may require this, but what is the benefit to the user/owner
of the machine?

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--

Previous thread: [RFC][PATCH 4/5]integrity: Linux Integrity Module(LIM) by Mimi Zohar on Friday, May 23, 2008 - 8:05 am. (6 messages)

Next thread: [PATCH] remove debug printk from DRM suspend path by Jesse Barnes on Friday, May 23, 2008 - 8:40 am. (1 message)