public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] integrity: TPM internel kernel interface
       [not found] <20080808184349.999902616@linux.vnet.ibm.com>
@ 2008-08-08 18:55 ` Mimi Zohar
  2008-08-09 18:46   ` Christoph Hellwig
  2008-08-08 18:55 ` [PATCH 2/4] integrity: special fs magic Mimi Zohar
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 18:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer, zohar

    Resubmitting integrity-tpm-internal-kernel-interface.patch, which
    was previously Signed-off-by Kylene Hall.
    Updated per feedback.
    
    Adds the following support:
    - make internal kernel interface to transmit TPM commands global
    - adds reading a pcr value
    - adds extending a pcr value
    - adds lookup the tpm_chip for given chip number and type
    
    Signed-off-by: Debora Velarde <debora@linux.vnet.ibm.com>
    
    Reviewed-by: James Morris <jmorris@namei.org>

Index: security-testing-2.6/drivers/char/tpm/tpm.c
===================================================================
--- security-testing-2.6.orig/drivers/char/tpm/tpm.c
+++ security-testing-2.6/drivers/char/tpm/tpm.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2004,2007,2008 IBM Corporation
  *
  * Authors:
  * Leendert van Doorn <leendert@watson.ibm.com>
  * Dave Safford <safford@watson.ibm.com>
  * Reiner Sailer <sailer@watson.ibm.com>
  * Kylene Hall <kjhall@us.ibm.com>
+ * Debora Velarde <dvelarde@us.ibm.com>
  *
  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  *
@@ -28,6 +29,13 @@
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/fs.h>
+#include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 #include "tpm.h"
 
 enum tpm_const {
@@ -50,6 +58,8 @@ enum tpm_duration {
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
 static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+#define TPM_CHIP_NUM_MASK       0x0000ffff
+#define TPM_CHIP_TYPE_SHIFT     16
 
 /*
  * Array with one entry per ordinal defining the maximum amount
@@ -366,8 +376,7 @@ EXPORT_SYMBOL_GPL(tpm_calc_ordinal_durat
 /*
  * Internal kernel interface to transmit TPM commands
  */
-static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
-			    size_t bufsiz)
+ssize_t tpm_transmit(struct tpm_chip *chip, char *buf, size_t bufsiz)
 {
 	ssize_t rc;
 	u32 count, ordinal;
@@ -425,6 +434,7 @@ out:
 	mutex_unlock(&chip->tpm_mutex);
 	return rc;
 }
+EXPORT_SYMBOL_GPL(tpm_transmit);
 
 #define TPM_DIGEST_SIZE 20
 #define TPM_ERROR_SIZE 10
@@ -710,6 +720,7 @@ ssize_t tpm_show_temp_deactivated(struct
 }
 EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
 
+#define READ_PCR_RESULT_SIZE 30
 static const u8 pcrread[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 14,		/* length */
@@ -765,6 +776,102 @@ out:
 }
 EXPORT_SYMBOL_GPL(tpm_show_pcrs);
 
+/*
+ * tpm_chip_lookup - return tpm_chip for given chip number and type
+ */
+static struct tpm_chip *tpm_chip_lookup(int chip_num, int chip_typ)
+{
+	struct tpm_chip *pos;
+
+	spin_lock(&driver_lock);
+	list_for_each_entry(pos, &tpm_chip_list, list) {
+		if ((chip_num == TPM_ANY_NUM || pos->dev_num == chip_num)
+		    && (chip_typ == TPM_ANY_TYPE)) {
+			spin_unlock(&driver_lock);
+			return pos;
+		}
+	}
+
+	spin_unlock(&driver_lock);
+	return NULL;
+}
+
+/**
+ * tpm_pcr_read - read a pcr value
+ * @chip_id: 	tpm chip identifier
+ * 		Upper 2 bytes: ANY, HW_ONLY or SW_ONLY
+ * 		Lower 2 bytes: tpm idx # or AN&
+ * @pcr_idx:	pcr idx to retrieve
+ * @res_buf: 	TPM_PCR value
+ * 		size of res_buf is 20 bytes (or NULL if you don't care)
+ */
+int tpm_pcr_read(u32 chip_id, int pcr_idx, u8 *res_buf)
+{
+	u8 data[READ_PCR_RESULT_SIZE];
+	int rc;
+	__be32 index;
+	int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+	struct tpm_chip *chip;
+
+	chip = tpm_chip_lookup(chip_num, chip_id >> TPM_CHIP_TYPE_SHIFT);
+	if (chip == NULL)
+		return -ENODEV;
+	BUILD_BUG_ON(sizeof(pcrread) > READ_PCR_RESULT_SIZE);
+	memcpy(data, pcrread, sizeof(pcrread));
+	index = cpu_to_be32(pcr_idx);
+	memcpy(data + 10, &index, 4);
+	rc = tpm_transmit(chip, data, sizeof(data));
+	if (rc > 0)
+		rc = get_unaligned_be32((__be32 *) (data + 6));
+
+	if (rc == 0 && res_buf)
+		memcpy(res_buf, data + 10, TPM_DIGEST_SIZE);
+
+	return rc;
+
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_read);
+
+#define EXTEND_PCR_SIZE 34
+static const u8 pcrextend[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 34,		/* length */
+	0, 0, 0, 20,		/* TPM_ORD_Extend */
+	0, 0, 0, 0		/* PCR index */
+};
+
+/**
+ * tpm_pcr_extend - extend pcr value with hash
+ * @chip_id: 	tpm chip identifier
+ * 		Upper 2 bytes: ANY, HW_ONLY or SW_ONLY
+ * 		Lower 2 bytes: tpm idx # or AN&
+ * @pcr_idx:	pcr idx to extend
+ * @hash: 	hash value used to extend pcr value
+ */
+int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8 *hash)
+{
+	u8 data[EXTEND_PCR_SIZE];
+	int rc;
+	__be32 index;
+	int chip_num = chip_id & TPM_CHIP_NUM_MASK;
+	struct tpm_chip *chip;
+
+	chip = tpm_chip_lookup(chip_num, chip_id >> TPM_CHIP_TYPE_SHIFT);
+	if (chip == NULL)
+		return -ENODEV;
+
+	BUILD_BUG_ON(sizeof(pcrextend) > EXTEND_PCR_SIZE);
+	memcpy(data, pcrextend, sizeof(pcrextend));
+	index = cpu_to_be32(pcr_idx);
+	memcpy(data + 10, &index, 4);
+	memcpy(data + 14, hash, TPM_DIGEST_SIZE);
+	rc = tpm_transmit(chip, data, sizeof(data));
+	if (rc > 0)
+		rc = get_unaligned_be32((__be32 *) (data + 6));
+	return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+
 #define  READ_PUBEK_RESULT_SIZE 314
 static const u8 readpubek[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
Index: security-testing-2.6/drivers/char/tpm/tpm.h
===================================================================
--- security-testing-2.6.orig/drivers/char/tpm/tpm.h
+++ security-testing-2.6/drivers/char/tpm/tpm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2004, 2007 IBM Corporation
  *
  * Authors:
  * Leendert van Doorn <leendert@watson.ibm.com>
@@ -26,6 +26,7 @@
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/tpm.h>
 
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
@@ -128,6 +129,7 @@ extern void tpm_get_timeouts(struct tpm_
 extern void tpm_gen_interrupt(struct tpm_chip *);
 extern void tpm_continue_selftest(struct tpm_chip *);
 extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+ssize_t tpm_transmit(struct tpm_chip *chip, char *buf, size_t bufsiz);
 extern struct tpm_chip* tpm_register_hardware(struct device *,
 				 const struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
Index: security-testing-2.6/include/linux/tpm.h
===================================================================
--- /dev/null
+++ security-testing-2.6/include/linux/tpm.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004,2007 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ * Debora Velarde <dvelarde@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_TPM_H__
+#define __LINUX_TPM_H__
+
+#define PCI_DEVICE_ID_AMD_8111_LPC    0x7468
+
+/*
+ * Chip type is one of these values in the upper two bytes of chip_id
+ */
+enum tpm_chip_type {
+	TPM_HW_TYPE = 0x0,
+	TPM_SW_TYPE = 0x1,
+	TPM_ANY_TYPE = 0xFFFF,
+};
+
+/*
+ * Chip num is this value or a valid tpm idx in lower two bytes of chip_id
+ */
+enum tpm_chip_num {
+	TPM_ANY_NUM = 0xFFFF,
+};
+
+
+#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
+
+extern int tpm_pcr_read(u32 chip_id, int pcr_idx, u8 *res_buf);
+extern int tpm_pcr_extend(u32 chip_id, int pcr_idx, const u8 *hash);
+#endif
+#endif

-- 


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

* [PATCH 2/4] integrity: special fs magic
       [not found] <20080808184349.999902616@linux.vnet.ibm.com>
  2008-08-08 18:55 ` [PATCH 1/4] integrity: TPM internel kernel interface Mimi Zohar
@ 2008-08-08 18:55 ` Mimi Zohar
  2008-08-08 19:04   ` Greg KH
  2008-08-08 23:15   ` Christoph Hellwig
  2008-08-08 18:56 ` [PATCH 3/4] integrity: Linux Integrity Module(LIM) Mimi Zohar
  2008-08-08 18:56 ` [PATCH 4/4] integrity: IMA as an integrity service provider Mimi Zohar
  3 siblings, 2 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 18:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer, zohar

    - Move special fs magic number definitions to magic.h
    - Add magic.h include
    
    Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
    
    Reviewed-by: James Morris <jmorris@namei.org>

Index: security-testing-2.6/fs/debugfs/inode.c
===================================================================
--- security-testing-2.6.orig/fs/debugfs/inode.c
+++ security-testing-2.6/fs/debugfs/inode.c
@@ -26,8 +26,7 @@
 #include <linux/debugfs.h>
 #include <linux/fsnotify.h>
 #include <linux/string.h>
-
-#define DEBUGFS_MAGIC	0x64626720
+#include <linux/magic.h>
 
 static struct vfsmount *debugfs_mount;
 static int debugfs_mount_count;
Index: security-testing-2.6/include/linux/magic.h
===================================================================
--- security-testing-2.6.orig/include/linux/magic.h
+++ security-testing-2.6/include/linux/magic.h
@@ -6,6 +6,10 @@
 #define AFS_SUPER_MAGIC                0x5346414F
 #define AUTOFS_SUPER_MAGIC	0x0187
 #define CODA_SUPER_MAGIC	0x73757245
+#define DEBUGFS_MAGIC          0x64626720
+#define SYSFS_MAGIC		0x62656572
+#define SECURITYFS_MAGIC	0x73636673
+#define TMPFS_MAGIC		0x01021994
 #define EFS_SUPER_MAGIC		0x414A53
 #define EXT2_SUPER_MAGIC	0xEF53
 #define EXT3_SUPER_MAGIC	0xEF53
Index: security-testing-2.6/mm/shmem.c
===================================================================
--- security-testing-2.6.orig/mm/shmem.c
+++ security-testing-2.6/mm/shmem.c
@@ -50,14 +50,12 @@
 #include <linux/migrate.h>
 #include <linux/highmem.h>
 #include <linux/seq_file.h>
+#include <linux/magic.h>
 
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 #include <asm/pgtable.h>
 
-/* This magic number is used in glibc for posix shared memory */
-#define TMPFS_MAGIC	0x01021994
-
 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
 #define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
 #define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
Index: security-testing-2.6/security/inode.c
===================================================================
--- security-testing-2.6.orig/security/inode.c
+++ security-testing-2.6/security/inode.c
@@ -20,8 +20,7 @@
 #include <linux/init.h>
 #include <linux/namei.h>
 #include <linux/security.h>
-
-#define SECURITYFS_MAGIC	0x73636673
+#include <linux/magic.h>
 
 static struct vfsmount *mount;
 static int mount_count;

-- 


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

* [PATCH 3/4] integrity: Linux Integrity Module(LIM)
       [not found] <20080808184349.999902616@linux.vnet.ibm.com>
  2008-08-08 18:55 ` [PATCH 1/4] integrity: TPM internel kernel interface Mimi Zohar
  2008-08-08 18:55 ` [PATCH 2/4] integrity: special fs magic Mimi Zohar
@ 2008-08-08 18:56 ` Mimi Zohar
  2008-08-09 18:53   ` Christoph Hellwig
  2008-08-08 18:56 ` [PATCH 4/4] integrity: IMA as an integrity service provider Mimi Zohar
  3 siblings, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 18:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer, zohar

    This version resolves the merge issues resulting from the removal of
    the nameidata parameter to inode_permission().
      - Moved the integrity_inode_permission() call from inode_permission()
        to vfs_inode_permission() and file_inode_permission().
      - Replaced the inode and nameidata parameters with file and path
        parameters to integrity_inode_permission().
 
    This patch is a redesign of the integrity framework, which address a
    number of issues, including
      - generalizing the measurement API beyond just inode measurements.
      - separation of the measurement into distinct collection, appraisal,
        and commitment phases, for greater flexibility.
    
    Extended Verification Module(EVM) and the Integrity Measurement
    Architecture(IMA) were originally implemented as an LSM module.  Based
    on discussions on the LSM mailing list, a decision was made that the
    LSM hooks should only be used to enforce mandatory access control
    decisions and a new set of hooks should be defined specifically for
    integrity.
    
    EVM/IMA was limited to verifying and measuring a file's (i.e. an inode)
    integrity and the metadata associated with it.  Current research is
    looking into other types of integrity measurements. (i.e. "Linux kernel
    integrity measurement using contextual inspection",  by Peter A. Loscocco,
    Perry W. Wilson, J. Aaron Pendergrass, C. Durward McDonell,
    http://doi.acm.org/10.1145/1314354.1314362). As a result, a requirement
    of the new integrity framework is support for different types of integrity
    measurements.
    
    This patch provides an integrity framework(api and hooks) and placement
    of the integrity hooks in the appropriate places in the fs directory.
    Collecting, appraising, and storing of file and other types of integrity
    data is supported.  Multiple integrity templates, which implement the
    integrity API, may register themselves.  For now, only a single integrity
    provider can register itself for the integrity hooks. (Support for multiple
    providers registering themselves for the integrity hooks would require
    some form of stacking.)
    
    The six integrity hooks are:
    	inode_permission, inode_alloc_integrity, inode_free_integrity,
    	bprm_check_integrity, file_free_integrity, file_mmap
    
    The five integrity API calls provided are:
    	integrity_must_measure, integrity_collect_measurement,
    	integrity_appraise_measurement, integrity_store_measurement,
    	and integrity_display_template.
    
    The type of integrity data being collected, appraised, stored, or
    displayed is template dependent.
    
    (Details on the calls and their exact arguments are in linux/integrity.h,
    included in the patch.)
    
    Signed-off-by: Mimi Zohar <zohar@us.ibm.com>

Index: security-testing-2.6/Documentation/kernel-parameters.txt
===================================================================
--- security-testing-2.6.orig/Documentation/kernel-parameters.txt
+++ security-testing-2.6/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.
+	INTEGRITY Integrity support 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.
@@ -878,6 +879,11 @@ and is between 256 and 4096 characters. 
 	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
 			Format: <irq>
 
+	integrity_audit= [INTEGRITY]
+                        Format: { "0" | "1" }
+                        0 -- disable integrity auditing messages.
+                        1 -- enable integrity auditing messages. (Default)
+
 	inttest=	[IA64]
 
 	iommu=		[x86]
Index: security-testing-2.6/fs/exec.c
===================================================================
--- security-testing-2.6.orig/fs/exec.c
+++ security-testing-2.6/fs/exec.c
@@ -45,6 +45,7 @@
 #include <linux/proc_fs.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/syscalls.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
@@ -1204,6 +1205,9 @@ int search_binary_handler(struct linux_b
 	retval = security_bprm_check(bprm);
 	if (retval)
 		return retval;
+	retval = integrity_bprm_check(bprm);
+	if (retval)
+		return retval;
 
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
Index: security-testing-2.6/fs/file_table.c
===================================================================
--- security-testing-2.6.orig/fs/file_table.c
+++ security-testing-2.6/fs/file_table.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/eventpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/mount.h>
@@ -272,6 +273,7 @@ void __fput(struct file *file)
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	integrity_file_free(file);
 	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
 		cdev_put(inode->i_cdev);
 	fops_put(file->f_op);
@@ -343,6 +345,7 @@ void put_filp(struct file *file)
 {
 	if (atomic_long_dec_and_test(&file->f_count)) {
 		security_file_free(file);
+		integrity_file_free(file);
 		file_kill(file);
 		file_free(file);
 	}
Index: security-testing-2.6/fs/inode.c
===================================================================
--- security-testing-2.6.orig/fs/inode.c
+++ security-testing-2.6/fs/inode.c
@@ -17,6 +17,7 @@
 #include <linux/hash.h>
 #include <linux/swap.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
@@ -151,6 +152,15 @@ static struct inode *alloc_inode(struct 
 			return NULL;
 		}
 
+		/* allocate, attach and initialize an i_integrity */
+		if (integrity_inode_alloc(inode)) {
+			if (inode->i_sb->s_op->destroy_inode)
+				inode->i_sb->s_op->destroy_inode(inode);
+			else
+				kmem_cache_free(inode_cachep, (inode));
+			return NULL;
+		}
+
 		spin_lock_init(&inode->i_lock);
 		lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
 
@@ -190,6 +200,7 @@ void destroy_inode(struct inode *inode) 
 {
 	BUG_ON(inode_has_buffers(inode));
 	security_inode_free(inode);
+	integrity_inode_free(inode);
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
 	else
Index: security-testing-2.6/fs/namei.c
===================================================================
--- security-testing-2.6.orig/fs/namei.c
+++ security-testing-2.6/fs/namei.c
@@ -24,6 +24,7 @@
 #include <linux/fsnotify.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
@@ -289,7 +290,14 @@ int inode_permission(struct inode *inode
  */
 int vfs_permission(struct nameidata *nd, int mask)
 {
-	return inode_permission(nd->path.dentry->d_inode, mask);
+	int retval;
+
+	retval = inode_permission(nd->path.dentry->d_inode, mask);
+	if (retval)
+		return retval;
+	return integrity_inode_permission(NULL, &nd->path,
+					  mask & (MAY_READ | MAY_WRITE |
+						  MAY_EXEC));
 }
 
 /**
@@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
  */
 int file_permission(struct file *file, int mask)
 {
-	return inode_permission(file->f_path.dentry->d_inode, mask);
+	int retval;
+
+	retval = inode_permission(file->f_path.dentry->d_inode, mask);
+	if (retval)
+		return retval;
+	return integrity_inode_permission(file, NULL,
+					  mask & (MAY_READ | MAY_WRITE |
+						  MAY_EXEC));
 }
 
 /*
Index: security-testing-2.6/include/linux/audit.h
===================================================================
--- security-testing-2.6.orig/include/linux/audit.h
+++ security-testing-2.6/include/linux/audit.h
@@ -123,6 +123,11 @@
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
+#define AUDIT_INTEGRITY_DATA	    1800 /* Data integrity verification */
+#define AUDIT_INTEGRITY_METADATA    1801 /* Metadata integrity verification */
+#define AUDIT_INTEGRITY_STATUS	    1802 /* Integrity enable status */
+#define AUDIT_INTEGRITY_HASH	    1803 /* Integrity HASH type */
+#define AUDIT_INTEGRITY_PCR	    1804 /* PCR invalidation msgs */
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
@@ -440,6 +445,8 @@ extern int  audit_set_loginuid(struct ta
 #define audit_get_loginuid(t) ((t)->loginuid)
 #define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
+extern void audit_log_inode_context(struct audit_buffer *ab,
+					struct inode *inode);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 extern int audit_bprm(struct linux_binprm *bprm);
@@ -520,6 +527,7 @@ extern int audit_signals;
 #define audit_get_loginuid(t) (-1)
 #define audit_get_sessionid(t) (-1)
 #define audit_log_task_context(b) do { ; } while (0)
+#define audit_log_inode_context(b, a) do {  } while (0)
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
Index: security-testing-2.6/include/linux/fs.h
===================================================================
--- security-testing-2.6.orig/include/linux/fs.h
+++ security-testing-2.6/include/linux/fs.h
@@ -680,6 +680,9 @@ struct inode {
 #ifdef CONFIG_SECURITY
 	void			*i_security;
 #endif
+#ifdef CONFIG_INTEGRITY
+	void			*i_integrity;
+#endif
 	void			*i_private; /* fs or device private pointer */
 };
 
Index: security-testing-2.6/include/linux/integrity.h
===================================================================
--- /dev/null
+++ security-testing-2.6/include/linux/integrity.h
@@ -0,0 +1,184 @@
+/*
+ * integrity.h
+ *
+ * Copyright (C) 2005,2006,2007,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.
+ */
+
+#ifndef _LINUX_INTEGRITY_H
+#define _LINUX_INTEGRITY_H
+
+#include <linux/fs.h>
+#include <linux/audit.h>
+
+#ifdef CONFIG_INTEGRITY
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			const unsigned char *fname, char *op,
+			char *cause, int result);
+
+/*
+ * Integrity API calls:
+ *
+ * @collect_measurement:
+ *	Collect template specific measurement data.
+ *	@data contains template specific data used for collecting the
+ *	measurement.
+ * 	Return 0 if operation was successful.
+ *
+ * @appraise_measurement:
+ *	Appraise the integrity of the template specific measurement data.
+ *	@data contains template specific data used for appraising the
+ *	measurement.
+ * 	Return 0 if operation was successful.
+ *
+ * @store_measurement:
+ *	Store the template specific data.
+ *	@data contains template specific data used for storing the
+ *	measurement.
+ *
+ * @must_measure:
+ *	Measurement decision based on an integrity policy.
+ *	@data contains template specific data used for making policy
+ * 	decision.
+ * 	Return 0 if operation was successful.
+ *
+ * @display_template:
+ *	Display template specific data.
+ *
+ */
+
+enum integrity_show_type { INTEGRITY_SHOW_BINARY, INTEGRITY_SHOW_ASCII};
+
+struct template_operations {
+	int (*collect_measurement)(void *);
+	int (*appraise_measurement)(void *);
+	void (*store_measurement)(void *);
+	int (*must_measure)(void *);
+	void (*display_template)(struct seq_file *m, void *,
+				 enum integrity_show_type);
+};
+extern int integrity_register_template(const char *template_name,
+					const struct template_operations *ops);
+extern int integrity_unregister_template(const char *template_name);
+extern int integrity_find_template(const char *,
+				   const struct template_operations **ops);
+
+/*
+ * Integrity hooks:
+ *
+ * @bprm_check_integrity:
+ * 	This hook mediates the point when a search for a binary handler	will
+ * 	begin.  At this point, the OS protects against an executable file,
+ * 	already open for write, from being executed; and an executable file
+ * 	already open for execute, from being modified. So we can be certain
+ *	that any measurements(collect, appraise, store) done here are of
+ * 	the file being executed.
+ * 	@bprm contains the linux_binprm structure.
+ *	Return 0 if the hook is successful and permission is granted.
+ *
+ * @inode_alloc_integrity:
+ *	Allocate and attach an integrity structure to @inode->i_integrity.  The
+ * 	i_integrity field is initialized to NULL when the inode structure is
+ * 	allocated.
+ * 	@inode contains the inode structure.
+ * 	Return 0 if operation was successful.
+ *
+ * @inode_free_integrity:
+ *	@inode contains the inode structure.
+ * 	Deallocate the inode integrity structure and set @inode->i_integrity to
+ * 	NULL.
+ *
+ * @inode_permission:
+ *	This hook is called by the existing Linux vfs_permission and
+ *      file_permission functions, as a file is opened.  At this point,
+ *	measurements(collect, appraise, store) of files open for read
+ * 	can be made.
+ *	@file contains the file structure of the file being opened(may be NULL).
+ *	@path contains the path structure (may be NULL).
+ *	@mask contains the permission mask.
+ *	Return 0 if the hook is successful and permission is granted.
+ *
+ * @file_free_integrity:
+ *	Update the integrity xattr value as necessary.
+ * 	@file contains the file structure being closed.
+ *
+ * @file_mmap :
+ *	Measurements(collect, appraise, store) of files mmaped for EXEC
+ *	can be made.
+ *	@file contains the file structure of the file to map (may be NULL).
+ *	@prot contains the protection that will be applied by the kernel.
+ *	Return 0 if the hook is successful and permission is granted.
+ */
+
+enum lim_hooks {INODE_PERMISSION = 1, FILE_MMAP, BPRM_CHECK };
+
+struct integrity_operations {
+	int (*bprm_check_integrity) (struct linux_binprm *bprm);
+	int (*inode_alloc_integrity) (struct inode *inode);
+	void (*inode_free_integrity) (struct inode *inode);
+	int (*inode_permission) (struct file *file, struct path *path,
+				 int mask);
+	void (*file_free_integrity) (struct file *file);
+	int (*file_mmap) (struct file *file, unsigned long prot);
+};
+extern int register_integrity(const struct integrity_operations *ops);
+extern int unregister_integrity(const struct integrity_operations *ops);
+
+/* global variables */
+extern const struct integrity_operations *integrity_ops;
+
+
+int integrity_collect_measurement(const char *template_name, void *data);
+int integrity_appraise_measurement(const char *template_name, void *data);
+int integrity_must_measure(const char *template_name, void *data);
+int integrity_store_measurement(const char *template_name, void *data);
+
+int integrity_bprm_check(struct linux_binprm *bprm);
+int integrity_inode_alloc(struct inode *inode);
+void integrity_inode_free(struct inode *inode);
+int integrity_inode_permission(struct file *file, struct path *path,int mask);
+void integrity_file_free(struct file *file);
+int integrity_file_mmap(struct file *file, unsigned long prot);
+#else
+
+static inline int integrity_bprm_check(struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline int integrity_inode_alloc(struct inode *inode)
+{
+	return 0;
+}
+
+static inline void integrity_inode_free(struct inode *inode)
+{
+	return;
+}
+
+static inline int integrity_inode_permission(struct file *file,
+					     struct path *path, int mask);
+{
+	return 0;
+}
+
+static inline int integrity_file_permission(struct file *file, int mask)
+{
+	return 0;
+}
+
+static inline void integrity_file_free(struct file *file)
+{
+	return;
+}
+
+static inline int integrity_file_mmap(struct file *file, unsigned long prot)
+{
+	return 0;
+}
+#endif
+#endif
Index: security-testing-2.6/mm/mmap.c
===================================================================
--- security-testing-2.6.orig/mm/mmap.c
+++ security-testing-2.6/mm/mmap.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
@@ -1046,6 +1047,9 @@ unsigned long do_mmap_pgoff(struct file 
 	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (error)
 		return error;
+	error = integrity_file_mmap(file, prot);
+	if (error)
+		return error;
 
 	return mmap_region(file, addr, len, flags, vm_flags, pgoff,
 			   accountable);
Index: security-testing-2.6/security/Kconfig
===================================================================
--- security-testing-2.6.orig/security/Kconfig
+++ security-testing-2.6/security/Kconfig
@@ -4,6 +4,8 @@
 
 menu "Security options"
 
+source security/integrity/Kconfig
+
 config KEYS
 	bool "Enable access key retention support"
 	help
Index: security-testing-2.6/security/Makefile
===================================================================
--- security-testing-2.6.orig/security/Makefile
+++ security-testing-2.6/security/Makefile
@@ -16,3 +16,7 @@ obj-$(CONFIG_SECURITY_SELINUX)		+= selin
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
+
+# Object integrity file lists
+subdir-$(CONFIG_INTEGRITY)		+= integrity
+obj-$(CONFIG_INTEGRITY)			+= integrity/built-in.o
Index: security-testing-2.6/security/integrity/Kconfig
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/Kconfig
@@ -0,0 +1,24 @@
+#
+# Integrity configuration
+#
+
+menu "Integrity options"
+
+config INTEGRITY
+	bool "Enable different integrity models"
+	help
+	  This allows you to choose different integrity modules to be
+	  configured into your kernel.
+
+	  If you are unsure how to answer this question, answer N.
+
+config INTEGRITY_AUDIT
+	bool "Integrity audit boot parameter"
+	depends on INTEGRITY
+	default y
+	help
+	  This option adds a kernel parameter 'integrity_audit', which
+	  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
Index: security-testing-2.6/security/integrity/Makefile
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel integrity code
+#
+
+# Object file lists
+obj-$(CONFIG_INTEGRITY)			+= integrity.o integrity_audit.o
Index: security-testing-2.6/security/integrity/integrity.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/integrity.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2006,2007,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.
+ *
+ * File: integrity.c
+ * 	register integrity subsystem
+ * 	register integrity template
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/integrity.h>
+
+const struct integrity_operations *integrity_ops;
+EXPORT_SYMBOL(integrity_ops);
+
+#define TEMPLATE_NAME_LEN_MAX 12
+struct template_list_entry {
+	struct list_head template;
+	char template_name[TEMPLATE_NAME_LEN_MAX + 1];
+	const struct template_operations *template_ops;
+};
+static LIST_HEAD(integrity_templates);
+static DEFINE_MUTEX(integrity_templates_mutex);
+
+/**
+ * register_integrity - registers an integrity framework with the kernel
+ * @ops: a pointer to the struct security_options that is to be registered
+ *
+ * Perhaps in the future integrity module stacking will be necessary, but
+ * for the time being, this function permits only one integrity module to
+ * register itself with the kernel integrity subsystem.
+ *
+ * If another integrity module is already registered, an error code is
+ * returned. On success 0 is returned.
+ */
+int register_integrity(const struct integrity_operations *ops)
+{
+	if (integrity_ops != NULL)
+		return -EAGAIN;
+	integrity_ops = ops;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(register_integrity);
+
+/**
+ * unregister_integrity - unregisters an integrity framework from the kernel
+ * @ops: a pointer to the struct security_options that is to be registered
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int unregister_integrity(const struct integrity_operations *ops)
+{
+	if (ops != integrity_ops)
+		return -EINVAL;
+
+	integrity_ops = NULL;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(unregister_integrity);
+
+/**
+ * integrity_register_template - registers an integrity template with the kernel
+ * @template_name: a pointer to a string containing the template name.
+ * @template_ops: a pointer to the template functions
+ *
+ * Register a set of functions to collect, appraise, store, and display
+ * a template measurement, and a means to decide whether to do them.
+ * Unlike integrity modules, any number of templates may be registered.
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_register_template(const char *template_name,
+				const struct template_operations *template_ops)
+{
+	int template_len;
+	struct template_list_entry *entry;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&entry->template);
+
+	template_len = strlen(template_name);
+	if (template_len > TEMPLATE_NAME_LEN_MAX)
+		return -EINVAL;
+	strcpy(entry->template_name, template_name);
+	entry->template_ops = template_ops;
+
+	mutex_lock(&integrity_templates_mutex);
+	list_add_rcu(&entry->template, &integrity_templates);
+	mutex_unlock(&integrity_templates_mutex);
+	synchronize_rcu();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(integrity_register_template);
+
+/**
+ * integrity_unregister_template: unregister a template
+ * @template_name: a pointer to a string containing the template name.
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int integrity_unregister_template(const char *template_name)
+{
+	struct template_list_entry *entry;
+
+	mutex_lock(&integrity_templates_mutex);
+	list_for_each_entry(entry, &integrity_templates, template) {
+		if (strncmp(entry->template_name, template_name,
+			    strlen(entry->template_name)) == 0) {
+			list_del_rcu(&entry->template);
+			mutex_unlock(&integrity_templates_mutex);
+			synchronize_rcu();
+			kfree(entry);
+			return 0;
+		}
+	}
+	mutex_unlock(&integrity_templates_mutex);
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL_GPL(integrity_unregister_template);
+
+/**
+ * integrity_find_template - search the integrity_templates list
+ * @template_name: a pointer to a string containing the template name.
+ * @template_ops: a pointer to the template functions
+ *
+ * Called with an rcu_read_lock
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int integrity_find_template(const char *template_name,
+			    const struct template_operations **template_ops)
+{
+	struct template_list_entry *entry;
+
+	list_for_each_entry_rcu(entry, &integrity_templates, template) {
+		if (strncmp(entry->template_name, template_name,
+			    strlen(entry->template_name)) == 0) {
+			*template_ops = entry->template_ops;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL_GPL(integrity_find_template);
+
+/* Start of the integrity API calls */
+
+/**
+ * integrity_collect_measurement - collect template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_collect_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->collect_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_collect_measurement);
+
+/**
+ * integrity_appraise_measurement - appraise template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure
+ */
+int integrity_appraise_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->appraise_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_appraise_measurement);
+
+/**
+ * integrity_store_measurement - store template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Store template specific integrity measurement.
+ */
+int integrity_store_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		template_ops->store_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_store_measurement);
+
+/**
+ * integrity_must_measure - measure decision based on template policy
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_must_measure(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->must_measure(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_must_measure);
+
+/* Start of the integrity Hooks */
+
+/* Hook used to measure executable file integrity. */
+int integrity_bprm_check(struct linux_binprm *bprm)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->bprm_check_integrity)
+		rc = integrity_ops->bprm_check_integrity(bprm);
+	return rc;
+}
+
+/* Allocate, attach and initialize an inode's i_integrity. */
+int integrity_inode_alloc(struct inode *inode)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->inode_alloc_integrity)
+		rc = integrity_ops->inode_alloc_integrity(inode);
+	return rc;
+}
+
+/* Hook used to free an inode's i_integrity structure. */
+void integrity_inode_free(struct inode *inode)
+{
+	if (integrity_ops && integrity_ops->inode_free_integrity)
+		integrity_ops->inode_free_integrity(inode);
+}
+
+/* Hook used to measure a file's integrity. */
+int integrity_inode_permission(struct file *file, struct path *path, int mask)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->inode_permission)
+		rc = integrity_ops->inode_permission(file, path, mask);
+	return rc;
+}
+
+/* Hook used to update i_integrity data and integrity xattr values
+ * as necessary.
+ */
+void integrity_file_free(struct file *file)
+{
+	if (integrity_ops && integrity_ops->file_free_integrity)
+		integrity_ops->file_free_integrity(file);
+}
+
+/* Hook used to measure integrity of an mmapped file */
+int integrity_file_mmap(struct file *file, unsigned long prot)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->file_mmap)
+		rc = integrity_ops->file_mmap(file, prot);
+	return rc;
+}
Index: security-testing-2.6/security/integrity/integrity_audit.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/integrity_audit.c
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ * File: integrity_audit.c
+ * 	Audit calls for the integrity subsystem
+ */
+
+#include <linux/audit.h>
+#include <linux/fs.h>
+#include <linux/integrity.h>
+
+static int integrity_audit = 1;
+
+#ifdef CONFIG_INTEGRITY_AUDIT
+static int __init integrity_audit_setup(char *str)
+{
+	ulong audit;
+	int rc;
+	char *op;
+
+	rc = strict_strtoul(str, 10, &audit);
+	if (rc < 0 || audit > 1)
+		printk(KERN_INFO "integrity: invalid integrity_audit value\n");
+	else
+		integrity_audit = audit;
+
+	op = integrity_audit ? "integrity_audit_enabled" :
+	    "integrity_audit_not_enabled";
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, NULL, op, 0);
+	return 1;
+}
+
+__setup("integrity_audit=", integrity_audit_setup);
+#endif
+
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, char *op,
+			 char *cause, int result)
+{
+	struct audit_buffer *ab;
+
+	if (!integrity_audit && result == 1)
+		return;
+
+	ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
+	audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u",
+			 current->pid, current->uid,
+			 audit_get_loginuid(current));
+	audit_log_task_context(ab);
+	switch (audit_msgno) {
+	case AUDIT_INTEGRITY_DATA:
+	case AUDIT_INTEGRITY_METADATA:
+	case AUDIT_INTEGRITY_PCR:
+		audit_log_format(ab, " op=%s cause=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_HASH:
+		audit_log_format(ab, " op=%s hash=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_STATUS:
+	default:
+		audit_log_format(ab, " op=%s", op);
+	}
+	audit_log_format(ab, " comm=");
+	audit_log_untrustedstring(ab, current->comm);
+	if (fname) {
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, fname);
+	}
+	if (inode)
+		audit_log_format(ab, " dev=%s ino=%lu",
+				 inode->i_sb->s_id, inode->i_ino);
+	audit_log_format(ab, " res=%d", result);
+	audit_log_end(ab);
+}

-- 


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

* [PATCH 4/4] integrity: IMA as an integrity service provider
       [not found] <20080808184349.999902616@linux.vnet.ibm.com>
                   ` (2 preceding siblings ...)
  2008-08-08 18:56 ` [PATCH 3/4] integrity: Linux Integrity Module(LIM) Mimi Zohar
@ 2008-08-08 18:56 ` Mimi Zohar
  2008-08-08 20:06   ` Randy Dunlap
  3 siblings, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 18:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer, zohar

    This is a re-release of Integrity Measurement Architecture(IMA) as an
    independent Linunx Integrity Module(LIM) service provider.

    This version addresses the merge issues resulting from the removal of
    the nameidata parameter to inode_permission().
    - The parameter changes to integrity_inode_permission() are reflected
      here in this patch.

    and extends the measurement policy definition language, based on 
    comments at OLS.
    - Added policy support for LSM subj_role, subj_type, and obj_role.
    - Added policy support for uid.
    - Constrained the default INODE_PERMISSION measurement to only measure
      files opened for read by root, using uid.
	
    and addresses linux-next testing issues: (updated)
    - Updated security/integrity/ima/Kconfig for LSM measurement policy 
    - Added dummy security_filter_rule_init/match routines for when 
      no LSM is configured.

    This version addresses a number of issues discussed on LKML, including:
    - Corrects the atomic_long_t variable usage, to use the appropriate
      atomic_long calls.
    - Added Documentation/ABI/testing/ima_policy which describes loading
      the IMA measurement policy.
    - Added policy support for magic numbers and removed them from
      skip_measurement().
    - Added policy support for LSM obj_type.
    - Replaced using .i_mtime to detect when a file has been modified
      with .i_version. This requires the filesystem to be mounted with
      iversion.  (Requires iversion mount support.)
    - Added const for integrity_template_operations.
    - Removed integrity_fixup_ops(), to make integrity_operations const too.
    - Removed ima_fixup_inodes() by registering the integrity_ops early in
      security_initcall(), but waiting to start IMA in late_initcall(), until
      after the TPM is available.
    - Removed CONFIG_IMA_BOOTPARAM and CONFIG_IMA_BOOTPARAM_VALUE.
    - Replaced,as appropriate, all GFP_ATOMICs with GFP_KERNEL.
    
    As a LIM integrity provider, IMA 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.
    
    IMA provides hardware (TPM) based measurement and attestation for both
    files and other types of template measurements. As the Trusted Computing
    (TPM) model requires, IMA measures all files before they are accessed
    in any way (on the bprm_check_integrity, file_mmap and inode_permission
    hooks), and commits the measurements to the TPM.  In addition, IMA
    maintains a list of these hash values, which can be used to validate
    the aggregate PCR value.  The TPM can sign these measurements, 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.
    
    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.
    
    As mentioned above, IMA maintains a list of hash values of executables
    and other sensitive system files loaded into the run-time of the system.
    Our work has shown that requests for integrity appraisal and measurement
    need to be based on knowledge of the filesystem, requiring the system
    to either be labeled with integrity data or depend on the existent LSM
    security labels.  The previous set of integrity patches modified the LSM
    modules to be integrity context aware, meaning that the LSM modules made
    integrity data/metadata appraisal and measurement API calls based on
    an understanding of the LSM security labels.  Both of the LSM maintainers
    felt that the changes were too intrusive and that integrity enforcement
    should be made by the integrity provider, not the LSM module.
    
    To address these concerns, Stephen Smalley suggested using the
    security_audit_rule_match(), renamed to security_filter_rule_match(), to
    define LSM specific integrity measurement policy rules, in lieu of
    modifying the LSM modules.  In the current set of patches, the integrity
    API calls can be made either by IMA, based on an LSM specific integrity
    policy, or by an integrity context aware LSM.
    
    Signed-off-by: Mimi Zohar <zohar@us.ibm.com>

Index: security-testing-2.6/Documentation/ABI/testing/ima_policy
===================================================================
--- /dev/null
+++ security-testing-2.6/Documentation/ABI/testing/ima_policy
@@ -0,0 +1,60 @@
+What:		security/ima/policy
+Date:		May 2008
+Contact:	Mimi Zohar <zohar@us.ibm.com>
+Description:
+		The Trusted Computing Group(TCG) runtime Integrity
+		Measurement Architecture(IMA) maintains a list of hash
+		values of executables and other sensitive system files
+		loaded into the run-time of this system.  At runtime,
+		the policy can be constrained based on LSM specific data.
+		Policies are loaded into security/ima/policy by opening
+		the file, writing the rules one at a time and then
+		closing the file.  The new policy takes effect after
+		the security/ima/policy is closed.
+
+		rule format: action [condition ...]
+
+		action: measure | dont_measure
+		condition:= base | lsm
+			base:	[[func=] [mask=] [fsmagic=] [uid=]]
+			lsm:	[[subj_user=] [subj_role=] [subj_type=]
+				 [obj_user=] [obj_role=] [obj_type=]]
+
+		base: 	func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION]
+			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
+			fsmagic:= hex value
+			uid:= decimal value
+		lsm:  	are LSM specific
+
+		default policy:
+			# PROC_SUPER_MAGIC
+			dont_measure fsmagic=0x9fa0
+			# SYSFS_MAGIC
+			dont_measure fsmagic=0x62656572
+			# DEBUGFS_MAGIC
+			dont_measure fsmagic=0x64626720
+			# TMPFS_MAGIC
+			dont_measure fsmagic=0x01021994
+			# SECURITYFS_MAGIC
+			dont_measure fsmagic=0x73636673
+			# SELINUX_MAGIC
+			dont_measure fsmagic=0xF97CFF8C
+
+			measure func=BPRM_CHECK
+			measure func=FILE_MMAP mask=MAY_EXEC
+			measure func=INODE_PERM mask=MAY_READ uid=0
+
+		The default policy measures all executables in bprm_check,
+		all files mmapped executable in file_mmap, and all files
+		open for read by root in inode_permission.
+
+		Examples of LSM specific definitions:
+
+		SELinux:
+			dont_measure obj_type=var_log_t
+			dont_measure obj_type=auditd_log_t
+			measure subj_user=system_u func=INODE_PERM mask=MAY_READ
+			measure subj_role=system_r func=INODE_PERM mask=MAY_READ
+
+		Smack:
+			measure subj_user=_ func=INODE_PERM mask=MAY_READ
Index: security-testing-2.6/Documentation/kernel-parameters.txt
===================================================================
--- security-testing-2.6.orig/Documentation/kernel-parameters.txt
+++ security-testing-2.6/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.
 	INTEGRITY Integrity support is enabled.
 	IOSCHED	More than one I/O scheduler is enabled.
 	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
@@ -862,6 +863,10 @@ and is between 256 and 4096 characters. 
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
 
+	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.
 
Index: security-testing-2.6/include/linux/ima.h
===================================================================
--- /dev/null
+++ security-testing-2.6/include/linux/ima.h
@@ -0,0 +1,46 @@
+/*
+ * ima.h
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_IMA_H
+#define _LINUX_IMA_H
+
+/* IMA LIM Data */
+enum ima_type { IMA_DATA, IMA_METADATA, IMA_TEMPLATE };
+
+struct ima_args_data {
+	const char	*filename;
+	struct file 	*file;
+	struct path 	*path;
+	struct dentry 	*dentry;
+	struct inode 	*inode;
+	enum lim_hooks	function;
+	u32		osid;
+	int 		mask;
+};
+
+struct ima_store_data {
+	char 		*name;
+	int 		len;
+	char 		*data;
+	int  		violation;
+};
+
+struct ima_data {
+	enum ima_type 	type;
+	union {
+		struct ima_args_data 	args;
+		struct ima_store_data	template;
+	} data;
+};
+
+void ima_fixup_argsdata(struct ima_args_data *data, struct file *file,
+			struct path *path, int mask, int function);
+#endif
Index: security-testing-2.6/security/integrity/Kconfig
===================================================================
--- security-testing-2.6.orig/security/integrity/Kconfig
+++ security-testing-2.6/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
Index: security-testing-2.6/security/integrity/Makefile
===================================================================
--- security-testing-2.6.orig/security/integrity/Makefile
+++ security-testing-2.6/security/integrity/Makefile
@@ -4,3 +4,5 @@
 
 # Object file lists
 obj-$(CONFIG_INTEGRITY)			+= integrity.o integrity_audit.o
+
+obj-$(CONFIG_IMA)			+= ima/
Index: security-testing-2.6/security/integrity/ima/Kconfig
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/Kconfig
@@ -0,0 +1,48 @@
+#
+# IBM Integrity Measurement Architecture
+#
+
+config IMA
+	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
+	select TCG_TIS
+	help
+	  The Trusted Computing Group(TCG) runtime Integrity
+	  Measurement Architecture(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_MEASURE_PCR_IDX
+	int "PCR for Aggregate (8<= Index <= 14)"
+	depends on IMA
+	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
+	default n
+	help
+	  Enable this option to allow the LSM module to enforce integrity.
+
+config IMA_LSM_RULES
+	bool "Enable LSM measurement policy rules"
+	depends on IMA && (SELINUX || SMACK)
+	default y
+	help
+	  Disabling this option will not enforce LSM based policy rules.
Index: security-testing-2.6/security/integrity/ima/Makefile
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for building Trusted Computing Group's(TCG) runtime Integrity
+# Measurement Architecture(IMA).
+#
+
+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
Index: security-testing-2.6/security/integrity/ima/ima.h
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * 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.
+ *
+ * File: ima.h
+ *	internal ima definitions
+ */
+
+#ifndef __LINUX_IMA_H
+#define __LINUX_IMA_H
+
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/security.h>
+#include <linux/integrity.h>
+#include <linux/hash.h>
+#include <linux/tpm.h>
+
+#define ima_printk(level, format, arg...)		\
+	printk(level "ima (%s): " format, __func__, ## arg)
+
+#define ima_error(format, arg...)	\
+	ima_printk(KERN_ERR, format, ## arg)
+
+#define ima_info(format, arg...)	\
+	ima_printk(KERN_INFO, format, ## arg)
+
+/* digest size for IMA, fits SHA1 or MD5 */
+#define IMA_DIGEST_SIZE		20
+#define IMA_EVENT_NAME_LEN_MAX	255
+
+#define IMA_HASH_BITS 9
+#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
+
+/* set during initialization */
+extern int ima_used_chip;
+extern char *ima_hash;
+
+struct ima_measure_entry {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1 or md5 measurement hash */
+	char template_name[IMA_EVENT_NAME_LEN_MAX + 1];	/* name + \0 */
+	int template_len;
+	char *template;
+};
+
+struct ima_queue_entry {
+	struct hlist_node hnext;	/* place in hash collision list */
+	struct list_head later;		/* place in ima_measurements list */
+	struct ima_measure_entry *entry;
+};
+extern struct list_head ima_measurements;	/* list of all measurements */
+
+/* declarations */
+extern int ima_template_mode;
+extern const struct template_operations ima_template_ops;
+
+/* Internal IMA function definitions */
+int ima_init(void);
+void ima_cleanup(void);
+int ima_fs_init(void);
+void ima_fs_cleanup(void);
+void ima_create_htable(void);
+int ima_add_measure_entry(struct ima_measure_entry *entry, int violation);
+struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest);
+int ima_calc_hash(struct file *file, struct path *path, char *digest);
+int ima_calc_template_hash(int template_len, char *template, char *digest);
+void ima_add_violation(struct inode *inode, const unsigned char *fname,
+			char *op, char *cause);
+
+enum ima_action {DONT_MEASURE, MEASURE};
+int ima_match_policy(struct inode *inode, enum lim_hooks func, int mask);
+int ima_add_rule(int, char *subj_user, char *subj_role, char *subj_type,
+		 char *obj_user, char *obj_role, char *obj_type,
+		 char *func, char *mask, char *fsmagic, char *uid);
+void ima_init_policy(void);
+void ima_update_policy(void);
+
+
+/* LIM API function definitions */
+int ima_must_measure(void *d);
+int ima_collect_measurement(void *d);
+int ima_appraise_measurement(void *d);
+void ima_store_measurement(void *d);
+void ima_template_show(struct seq_file *m, void *e,
+			     enum integrity_show_type show);
+
+
+/*
+ * used to protect h_table and sha_table
+ */
+extern spinlock_t ima_queue_lock;
+
+struct ima_h_table {
+	atomic_long_t len;	/* number of stored measurements in the list */
+	atomic_long_t violations;
+	unsigned int max_htable_size;
+	struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
+	atomic_t queue_len[IMA_MEASURE_HTABLE_SIZE];
+};
+extern struct ima_h_table ima_htable;
+
+static inline unsigned long IMA_HASH_KEY(u8 *digest)
+{
+	 return(hash_ptr(digest, IMA_HASH_BITS));
+}
+
+/* TPM "Glue" definitions */
+
+#define IMA_TPM ((((u32)TPM_ANY_TYPE)<<16) | (u32)TPM_ANY_NUM)
+static inline void ima_extend(const u8 *hash)
+{
+	if (!ima_used_chip)
+		return;
+
+	if (tpm_pcr_extend(IMA_TPM, CONFIG_IMA_MEASURE_PCR_IDX, hash) != 0)
+		ima_error("Error Communicating to TPM chip\n");
+}
+
+static inline void ima_pcrread(int idx, u8 *pcr, int pcr_size)
+{
+	if (!ima_used_chip)
+		return;
+
+	if (tpm_pcr_read(IMA_TPM, idx, pcr) != 0)
+		ima_error("Error Communicating to TPM chip\n");
+}
+
+struct ima_inode_measure_entry {
+	u8 digest[IMA_DIGEST_SIZE];	/* sha1/md5 measurement hash */
+	char file_name[IMA_EVENT_NAME_LEN_MAX + 1];	/* name + \0 */
+};
+
+/* inode integrity data */
+struct ima_iint_cache {
+	u64 		version;
+	int 		measured;
+	u8 		hmac[IMA_DIGEST_SIZE];
+	u8 		digest[IMA_DIGEST_SIZE];
+	struct mutex mutex;
+};
+
+/* LSM based policy rules require audit */
+#ifdef CONFIG_IMA_LSM_RULES
+
+#define security_filter_rule_init security_audit_rule_init
+#define security_filter_rule_match security_audit_rule_match
+
+#else
+
+static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
+					    void **lsmrule)
+{
+	return -EINVAL;
+}
+
+static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
+				   void *lsmrule, struct audit_context *actx)
+{
+	return -EINVAL;
+}
+#endif
+#endif
Index: security-testing-2.6/security/integrity/ima/ima_api.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_api.c
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ *
+ * File: ima_api.c
+ *            - implements the LIM API
+ */
+#include <linux/module.h>
+#include <linux/integrity.h>
+#include <linux/magic.h>
+#include <linux/writeback.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/audit.h>
+#include <linux/ima.h>
+
+#include "ima.h"
+
+const struct template_operations ima_template_ops = {
+	.must_measure = ima_must_measure,
+	.collect_measurement = ima_collect_measurement,
+	.store_measurement = ima_store_measurement,
+	.display_template = ima_template_show
+};
+
+/**
+ * mode_setup - for compatability with non-template IMA versions
+ * @str: is pointer to a string
+ */
+int ima_template_mode = 1;
+static int __init mode_setup(char *str)
+{
+	if (strncmp(str, "ima", 3) == 0)
+		ima_template_mode = 0;
+	if (strncmp(str, "template", 7) == 0)
+		ima_template_mode = 1;
+	ima_info("template_mode %s \n",
+		  ima_template_mode ? "template" : "ima");
+	return 1;
+}
+
+__setup("ima_mode=", mode_setup);
+
+/**
+ * ima_digest_cpy - copy the hash in the IMA template structure to a digest
+ * @template_name: string containing the name of the template (i.e. "ima")
+ * @template: pointer to template structure
+ * @digest: pointer to the digest
+ *
+ * Returns 0 on success, error code otherwise
+ */
+static int ima_digest_cpy(char *template_name, void *template, u8 *digest)
+{
+	int rc, result = 0;
+	struct ima_inode_measure_entry *inode_template =
+	    (struct ima_inode_measure_entry *)template;
+
+	rc = strcmp(template_name, "ima");
+	if (rc == 0)
+		memcpy(digest, inode_template->digest,
+		       sizeof inode_template->digest);
+	else
+		result = -ENODATA;
+	return result;
+}
+
+/**
+ * ima_store_template_measure - collect and protect template measurements
+ * @template_name: string containing the name of the template (i.e. "ima")
+ * @template_len: length of the template data
+ * @template: actual template data
+ * @violation: invalidate pcr measurement indication
+ * @audit_cause: string containing the audit failure cause
+ *
+ * Calculate the hash of a template entry, add the template entry
+ * to an ordered list of measurement entries maintained inside the kernel,
+ * and also update the aggregate integrity value (maintained inside the
+ * configured TPM PCR) over the hashes of the current list of measurement
+ * entries.
+ *
+ * Applications retrieve the current kernel-held measurement list through
+ * the securityfs entries in /sys/kernel/security/ima. The signed aggregate
+ * TPM PCR (called quote) can be retrieved using a TPM user space library
+ * and is used to validate the measurement list.
+ *
+ * Returns 0 on success, error code otherwise
+ */
+static int ima_store_template_measure(char *template_name, int template_len,
+				      char *template, int violation,
+				      char **audit_cause)
+{
+	struct ima_measure_entry *entry;
+	u8 digest[IMA_DIGEST_SIZE];
+	struct ima_queue_entry *qe;
+	int count, result = 0;
+
+	memset(digest, 0, IMA_DIGEST_SIZE);
+	if (!violation) {
+		int rc = -ENODATA;
+
+		if (!ima_template_mode)
+			rc = ima_digest_cpy(template_name, template, digest);
+		if (rc < 0)
+			result = ima_calc_template_hash(template_len, template,
+							digest);
+
+		/* hash exists already? */
+		qe = ima_lookup_digest_entry(digest);
+		if (qe) {
+			*audit_cause = "hash_exists";
+			result = -EEXIST;
+			goto out;
+		}
+	}
+
+	/* create new entry and add to measurement list */
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		*audit_cause = "ENOMEM";
+		result = -ENOMEM;
+		goto out;
+	}
+
+	entry->template = kzalloc(template_len, GFP_KERNEL);
+	if (!entry->template) {
+		*audit_cause = "ENOMEM";
+		result = -ENOMEM;
+		goto out;
+	}
+	if (!template_name) {
+		*audit_cause = "null_template_name";
+		count = 1;
+	} else {
+		count = strlen(template_name);
+		if (count > IMA_EVENT_NAME_LEN_MAX)
+			count = IMA_EVENT_NAME_LEN_MAX;
+		memcpy(entry->template_name, template_name, count);
+	}
+	entry->template_name[count] = '\0';
+	entry->template_len = template_len;
+	memcpy(entry->template, template, template_len);
+	memcpy(entry->digest, digest, IMA_DIGEST_SIZE);
+
+	result = ima_add_measure_entry(entry, violation);
+	if (result < 0)
+		kfree(entry);
+out:
+	return result;
+}
+
+/**
+ * ima_store_inode_measure - create and store an inode template measurement
+ * @name: ascii file name associated with the measurement hash
+ * @hash_len: length of hash value in bytes (16 for MD5, 20 for SHA1)
+ * @hash: actual hash value pre-calculated
+ *
+ * Returns 0 on success, error code otherwise
+ */
+static int ima_store_inode_measure(struct inode *inode,
+				   const unsigned char *name,
+				   int hash_len, char *hash, int violation)
+{
+	struct ima_inode_measure_entry measure_entry, *entry = &measure_entry;
+	int result;
+	int namelen;
+	char *op = "add_measure";
+	char *cause = " ";
+
+	memset(entry, 0, sizeof *entry);
+	if (!violation)
+		memcpy(entry->digest, hash, hash_len > IMA_DIGEST_SIZE ?
+		       IMA_DIGEST_SIZE : hash_len);
+	if (name) {
+		namelen = strlen(name);
+		memcpy(entry->file_name, name, namelen > IMA_EVENT_NAME_LEN_MAX
+		       ? IMA_EVENT_NAME_LEN_MAX : namelen);
+		entry->file_name[namelen] = '\0';
+	}
+	result = ima_store_template_measure("ima", sizeof *entry, (char *)entry,
+					    violation, &cause);
+	if (result < 0)
+		integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
+				    name, op, cause, result);
+	return result;
+}
+
+/**
+ * ima_add_violation - add violation to measurement list.
+ * @inode: inode associated with the violation
+ * @fname: name associated with the inode
+ * @op: string pointer to audit operation (i.e. "invalid_pcr", "add_measure")
+ * @cause: string pointer to reason for violation (i.e. "ToMToU")
+ *
+ * Violations are flagged in the measurement list with zero hash values.
+ * By extending the PCR with 0xFF's instead of with zeroes, the PCR
+ * value is invalidated.
+ */
+void ima_add_violation(struct inode *inode, const unsigned char *fname,
+		       char *op, char *cause)
+{
+	int result;
+
+	/* can overflow, only indicator */
+	atomic_long_inc(&ima_htable.violations);
+
+	result = ima_store_inode_measure(inode, fname, 0, NULL, 1);
+	integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, fname, op,
+			    cause, result);
+}
+
+/**
+ * skip_measurement - measure only regular files, skip everything else.
+ * @inode: inode being measured
+ * @mask: contains the permission mask
+ *
+ * Quick sanity check to make sure that only regular files opened
+ * for read-only or execute are measured.
+ *
+ * Return 1 to skip measure, 0 to measure
+ */
+static int skip_measurement(struct inode *inode, int mask)
+{
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+		return 1;	/* can't measure */
+
+	if (special_file(inode->i_mode) || S_ISLNK(inode->i_mode))
+		return 1;	/* don't measure */
+
+	if (S_ISREG(inode->i_mode))
+		return 0;	/* measure */
+	return 1;		/* don't measure */
+}
+
+/**
+ * ima_must_measure - measure decision based on policy.
+ * @template_data: pointer to struct ima_data containing ima_args_data
+ *
+ * The policy is defined in terms of keypairs:
+ * 		subj=, obj=, type=, func=, mask=, fsmagic=
+ *	subj,obj, and type: are LSM specific.
+ * 	func: INODE_PERMISSION | BPRM_CHECK | FILE_MMAP
+ * 	mask: contains the permission mask
+ *	fsmagic: hex value
+ *
+ * Return 0 to measure. For matching a DONT_MEASURE policy, no policy,
+ * or other error, return an error code.
+*/
+int ima_must_measure(void *template_data)
+{
+	struct ima_data *idata = (struct ima_data *)template_data;
+	struct ima_args_data *data = &idata->data.args;
+	int rc;
+
+	if ((data->mask & MAY_WRITE) || (data->mask & MAY_APPEND))
+		return -EPERM;
+
+	if (skip_measurement(data->inode, data->mask))
+		return -EPERM;
+
+	rc = ima_match_policy(data->inode, data->function, data->mask);
+	if (rc)
+		return 0;
+	return -EACCES;
+}
+
+/**
+ * ima_collect_measurement - collect file measurements and store in the inode
+ * @template_data: pointer to struct ima_data containing ima_args_data
+ *
+ * Return 0 on success, error code otherwise
+ */
+int ima_collect_measurement(void *template_data)
+{
+	struct ima_iint_cache *iint;
+	struct ima_data *idata = (struct ima_data *)template_data;
+	struct ima_args_data *data = &idata->data.args;
+	struct dentry *dentry = data->dentry;
+	struct inode *inode = data->inode;
+	int result = 0;
+
+	if (idata->type != IMA_DATA)
+		return -EPERM;
+
+	if (!inode || !dentry)
+		return -EINVAL;
+
+	iint = inode->i_integrity;
+	mutex_lock(&iint->mutex);
+	if (!iint->measured) {
+		memset(iint->digest, 0, IMA_DIGEST_SIZE);
+		result = ima_calc_hash(data->file, data->path, iint->digest);
+	} else
+		result = -EEXIST;
+	mutex_unlock(&iint->mutex);
+	return result;
+}
+
+/**
+ * ima_store_measurement - store file and template measurements
+ * @template_data: pointer to struct ima_data containing ima_args_data,
+ * used to create an IMA template, or a template.
+ *
+ * For file measurements, first create an IMA template and then store it.
+ * For all other types of template measurements, just store it.
+ */
+void ima_store_measurement(void *template_data)
+{
+	struct ima_data *idata = (struct ima_data *)template_data;
+	int result;
+	char *op = "add_template_measure";
+	char *cause = "";
+
+	if (idata->type == IMA_DATA) {
+		struct ima_args_data *data = &idata->data.args;
+		struct ima_iint_cache *iint;
+
+		iint = data->inode->i_integrity;
+		mutex_lock(&iint->mutex);
+		if (iint->measured) {
+			mutex_unlock(&iint->mutex);
+			return;
+		}
+		result = ima_store_inode_measure(data->inode, data->filename,
+						 IMA_DIGEST_SIZE, iint->digest,
+						 0);
+		if (!result || result == -EEXIST) {
+			iint->measured = 1;
+			iint->version = data->inode->i_version;
+		}
+		mutex_unlock(&iint->mutex);
+	} else if (idata->type == IMA_TEMPLATE) {
+		struct ima_store_data *template = (struct ima_store_data *)
+		    &idata->data.template;
+
+		result = ima_store_template_measure(template->name,
+						    template->len,
+						    template->data, 0, &cause);
+		if (result < 0)
+			integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL,
+					    template->name, op, cause, result);
+	}
+}
Index: security-testing-2.6/security/integrity/ima/ima_crypto.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_crypto.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Mimi Zohar <zohar@us.ibm.com>
+ * Kylene Hall <kjhall@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.
+ *
+ * File: ima_crypto.c
+ * 	Calculate a file's or a template's hash.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/scatterlist.h>
+#include <linux/namei.h>
+#include "ima.h"
+
+/*
+ * Calculate the file hash, using an open file descriptor if available.
+ */
+static int update_file_hash(struct file *f, struct path *path,
+			    struct hash_desc *desc)
+{
+	struct file *file = f;
+	struct scatterlist sg[1];
+	loff_t i_size;
+	int rc = 0;
+	char *rbuf;
+	int offset = 0;
+
+	if (!file) {
+		struct dentry *de = dget(path->dentry);
+		struct vfsmount *mnt = mntget(path->mnt);
+		if (!de || !mnt) {
+			rc = -EINVAL;
+			goto err_out;
+		}
+		file = dentry_open(de, mnt, O_RDONLY);
+		if (IS_ERR(file)) {
+			ima_info("%s dentry_open failed\n", de->d_name.name);
+			rc = PTR_ERR(file);
+			file = NULL;
+		}
+err_out:
+		if (!file) {
+			dput(de);
+			mntput(mnt);
+			goto out;
+		}
+	}
+
+	if (!file->f_dentry || !file->f_dentry->d_inode) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!rbuf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	i_size = i_size_read(file->f_dentry->d_inode);
+	while (offset < i_size) {
+		int rbuf_len;
+
+		rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
+		if (rbuf_len < 0) {
+			rc = rbuf_len;
+			break;
+		}
+		offset += rbuf_len;
+		sg_set_buf(sg, rbuf, rbuf_len);
+
+		rc = crypto_hash_update(desc, sg, rbuf_len);
+		if (rc)
+			break;
+	}
+	kfree(rbuf);
+out:
+	if (file && !f)
+		fput(file);	/* clean up dentry_open() */
+	return rc;
+}
+
+/*
+ * Calculate the MD5/SHA1 digest
+ */
+int ima_calc_hash(struct file *file, struct path *path, char *digest)
+{
+	struct hash_desc desc;
+	int rc;
+
+	if (!file && !path)
+		return -EINVAL;
+
+	desc.tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc.tfm)) {
+		ima_info("failed to load %s transform: %ld\n",
+			 ima_hash, PTR_ERR(desc.tfm));
+		rc = PTR_ERR(desc.tfm);
+		return rc;
+	}
+	desc.flags = 0;
+	rc = crypto_hash_init(&desc);
+	if (rc)
+		goto out;
+
+	rc = update_file_hash(file, path, &desc);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+out:
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
+
+/*
+ * Calculate the hash of a given template
+ */
+int ima_calc_template_hash(int template_len, char *template, char *digest)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int rc;
+
+	desc.tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc.tfm)) {
+		ima_info("failed to load %s transform: %ld\n",
+			 ima_hash, PTR_ERR(desc.tfm));
+		rc = PTR_ERR(desc.tfm);
+		return rc;
+	}
+	desc.flags = 0;
+	rc = crypto_hash_init(&desc);
+	if (rc)
+		goto out;
+
+	sg_set_buf(sg, template, template_len);
+	rc = crypto_hash_update(&desc, sg, template_len);
+	if (!rc)
+		rc = crypto_hash_final(&desc, digest);
+out:
+	crypto_free_hash(desc.tfm);
+	return rc;
+}
Index: security-testing-2.6/security/integrity/ima/ima_fs.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_fs.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Kylene Hall <kjhall@us.ibm.com>
+ * Reiner Sailer <sailer@us.ibm.com>
+ * 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.
+ *
+ * File: ima_fs.c
+ *	implemenents security file system for reporting
+ *	current measurement list and IMA statistics
+ */
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/integrity.h>
+
+#include "ima.h"
+
+#define TMPBUFLEN 12
+static ssize_t ima_show_htable_value(char __user *buf, size_t count,
+				     loff_t *ppos, atomic_long_t *val)
+{
+	char tmpbuf[TMPBUFLEN];
+	ssize_t len;
+
+	len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
+}
+
+static ssize_t ima_show_htable_violations(struct file *filp,
+					  char __user *buf,
+					  size_t count, loff_t *ppos)
+{
+	return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
+}
+
+static struct file_operations ima_htable_violations_ops = {
+	.read = ima_show_htable_violations
+};
+
+static ssize_t ima_show_measurements_count(struct file *filp,
+					   char __user *buf,
+					   size_t count, loff_t *ppos)
+{
+	return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
+
+}
+
+static struct file_operations ima_measurements_count_ops = {
+	.read = ima_show_measurements_count
+};
+
+/* returns pointer to hlist_node */
+static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
+{
+	struct list_head *lpos;
+	loff_t l = *pos;
+	/* we need a lock since pos could point beyond last element */
+	rcu_read_lock();
+	list_for_each_rcu(lpos, &ima_measurements) {
+		if (!l--) {
+			rcu_read_unlock();
+			return lpos;
+		}
+	}
+	rcu_read_unlock();
+	return NULL;
+}
+
+static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	/* lock protects when reading beyond last element
+	 * against concurrent list-extension */
+	struct list_head *lpos = (struct list_head *)v;
+
+	rcu_read_lock();
+	lpos = rcu_dereference(lpos->next);
+	rcu_read_unlock();
+	(*pos)++;
+
+	return (lpos == &ima_measurements) ? NULL : lpos;
+}
+
+static void ima_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+/* print format:
+ *       32bit-le=pcr#
+ *       char[20]=template digest
+ *       32bit-le=template size
+ *       32bit-le=template name size
+ *       eventdata[n] = template name
+ *
+ */
+static int ima_measurements_show(struct seq_file *m, void *v)
+{
+	/* the list never shrinks, so we don't need a lock here */
+	struct list_head *lpos = v;
+	struct ima_queue_entry *qe;
+	struct ima_measure_entry *e;
+	struct ima_inode_measure_entry *entry;
+	const struct template_operations *template_ops;
+	int templatename_len;
+	int i;
+	u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+	char data[4];
+
+	/* get entry */
+	qe = list_entry(lpos, struct ima_queue_entry, later);
+	e = qe->entry;
+	if (e == NULL)
+		return -1;
+
+	/*
+	 * 1st: PCRIndex
+	 * PCR used is always the same (config option) in
+	 * little-endian format
+	 */
+	memcpy(data, &pcr, 4);
+	for (i = 0; i < 4; i++)
+		seq_putc(m, data[i]);
+
+	/* 2nd: template digest */
+	for (i = 0; i < 20; i++)
+		seq_putc(m, e->digest[i]);
+
+	/* 3rd: template name size */
+	templatename_len = strlen(e->template_name);
+	if (templatename_len > IMA_EVENT_NAME_LEN_MAX)
+		templatename_len = IMA_EVENT_NAME_LEN_MAX;
+
+	memcpy(data, &templatename_len, 4);
+	for (i = 0; i < 4; i++)
+		seq_putc(m, data[i]);
+
+	/* 4th:  template name  */
+	for (i = 0; i < templatename_len; i++)
+		seq_putc(m, e->template_name[i]);
+
+	/* 5th:  template dependent */
+	entry = (struct ima_inode_measure_entry *)e->template;
+	if (integrity_find_template(e->template_name, &template_ops) == 0)
+		template_ops->display_template(m, entry, INTEGRITY_SHOW_BINARY);
+	else
+		seq_printf(m, " \n");
+	return 0;
+}
+
+static struct seq_operations ima_measurments_seqops = {
+	.start = ima_measurements_start,
+	.next = ima_measurements_next,
+	.stop = ima_measurements_stop,
+	.show = ima_measurements_show
+};
+
+static int ima_measurements_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ima_measurments_seqops);
+}
+
+static struct file_operations ima_measurements_ops = {
+	.open = ima_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+void ima_template_show(struct seq_file *m, void *e,
+		       enum integrity_show_type show)
+{
+	struct ima_inode_measure_entry *entry =
+	    (struct ima_inode_measure_entry *)e;
+	int filename_len;
+	char data[4];
+	int i;
+
+	/* Display file digest */
+	if (ima_template_mode)
+		for (i = 0; i < 20; i++) {
+			switch (show) {
+			case INTEGRITY_SHOW_ASCII:
+				seq_printf(m, "%02x", entry->digest[i]);
+				break;
+			case INTEGRITY_SHOW_BINARY:
+				seq_putc(m, entry->digest[i]);
+			default:
+				break;
+			}
+		}
+
+	switch (show) {
+	case INTEGRITY_SHOW_ASCII:
+		seq_printf(m, " %s\n", entry->file_name);
+		break;
+	case INTEGRITY_SHOW_BINARY:
+		filename_len = strlen(entry->file_name);
+		if (filename_len > IMA_EVENT_NAME_LEN_MAX)
+			filename_len = IMA_EVENT_NAME_LEN_MAX;
+
+		memcpy(data, &filename_len, 4);
+		for (i = 0; i < 4; i++)
+			seq_putc(m, data[i]);
+		for (i = 0; i < filename_len; i++)
+			seq_putc(m, entry->file_name[i]);
+	default:
+		break;
+	}
+}
+
+/* print in ascii */
+static int ima_ascii_measurements_show(struct seq_file *m, void *v)
+{
+	/* the list never shrinks, so we don't need a lock here */
+	struct list_head *lpos = v;
+	struct ima_queue_entry *qe;
+	struct ima_measure_entry *e;
+	struct ima_inode_measure_entry *entry;
+	const struct template_operations *template_ops;
+	int i;
+
+	/* get entry */
+	qe = list_entry(lpos, struct ima_queue_entry, later);
+	e = qe->entry;
+	if (e == NULL)
+		return -1;
+
+	/* 1st: PCR used (config option) */
+	seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
+
+	/* 2nd: SHA1 template hash */
+	for (i = 0; i < 20; i++)
+		seq_printf(m, "%02x", e->digest[i]);
+
+	/* 3th:  template name */
+	seq_printf(m, " %s ", e->template_name);
+
+	/* 4th:  filename <= max + \'0' delimiter */
+	entry = (struct ima_inode_measure_entry *)e->template;
+	if (integrity_find_template(e->template_name, &template_ops) == 0)
+		template_ops->display_template(m, entry, INTEGRITY_SHOW_ASCII);
+	else
+		seq_printf(m, " \n");
+
+	return 0;
+}
+
+static struct seq_operations ima_ascii_measurements_seqops = {
+	.start = ima_measurements_start,
+	.next = ima_measurements_next,
+	.stop = ima_measurements_stop,
+	.show = ima_ascii_measurements_show
+};
+
+static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ima_ascii_measurements_seqops);
+}
+
+static struct file_operations ima_ascii_measurements_ops = {
+	.open = ima_ascii_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static char *get_tag(char *bufStart, char *bufEnd, char delimiter, int *taglen)
+{
+	char *bufp = bufStart;
+	char *tag;
+
+	/* Get start of tag */
+	while (bufp < bufEnd) {
+		if (*bufp == ' ')	/* skip blanks */
+			while ((*bufp == ' ') && (bufp++ < bufEnd)) ;
+		else if (*bufp == '#') {	/* skip comment */
+			while ((*bufp != '\n') && (bufp++ < bufEnd)) ;
+			bufp++;
+		} else if (*bufp == '\n')	/* skip newline */
+			bufp++;
+		else if (*bufp == '\t')	/* skip tabs */
+			bufp++;
+		else
+			break;
+	}
+	if (bufp < bufEnd)
+		tag = bufp;
+	else
+		return NULL;
+
+	/* Get tag */
+	*taglen = 0;
+	while ((bufp < bufEnd) && (*taglen == 0)) {
+		if ((*bufp == delimiter) || (*bufp == '\n')) {
+			*taglen = bufp - tag;
+			*bufp = '\0';
+		}
+		bufp++;
+	}
+	if (*taglen == 0)	/* Didn't find end delimiter */
+		tag = NULL;
+	return tag;
+}
+
+static ssize_t ima_write_policy(struct file *file, const char __user *buf,
+				size_t buflen, loff_t *ppos)
+{
+	size_t rc = 0, datalen;
+	int action = 0;
+	char *data, *datap, *dataend;
+	char *subj_user = NULL, *subj_role = NULL, *subj_type = NULL;
+	char *obj_user = NULL, *obj_role = NULL, *obj_type = NULL;
+	char *func = NULL, *mask = NULL, *fsmagic = NULL, *uid = NULL;
+	int err = 0;
+	char *tag;
+	int taglen, i;
+
+	datalen = buflen > 4095 ? 4095 : buflen;
+	data = kmalloc(datalen + 1, GFP_KERNEL);
+	if (!data)
+		rc = -ENOMEM;
+
+	if (copy_from_user(data, buf, datalen)) {
+		kfree(data);
+		return -EFAULT;
+	}
+
+	rc = datalen;
+	*(data + datalen) = ' ';
+
+	datap = data;
+	dataend = data + datalen;
+
+	if (strncmp(datap, "measure", 7) == 0) {
+		datap += 8;
+		action = 1;
+	} else if (strncmp(datap, "dont_measure", 12) == 0)
+		datap += 13;
+	else			/* bad format */
+		goto out;
+
+	for (i = 0; i < 6; i++) {
+		tag = get_tag(datap, dataend, ' ', &taglen);
+		if (!tag)
+			break;
+		if (strncmp(tag, "obj_user=", 9) == 0)
+			obj_user = tag + 9;
+		else if (strncmp(tag, "obj_role=", 9) == 0)
+			obj_role = tag + 9;
+		else if (strncmp(tag, "obj_type=", 9) == 0)
+			obj_type = tag + 9;
+		else if (strncmp(tag, "subj_user=", 10) == 0)
+			subj_user = tag + 10;
+		else if (strncmp(tag, "subj_role=", 10) == 0)
+			subj_role = tag + 10;
+		else if (strncmp(tag, "subj_type=", 10) == 0)
+			subj_type = tag + 10;
+		else if (strncmp(tag, "func=", 5) == 0)
+			func = tag + 5;
+		else if (strncmp(tag, "mask=", 5) == 0)
+			mask = tag + 5;
+		else if (strncmp(tag, "fsmagic=", 8) == 0)
+			fsmagic = tag + 8;
+		else if (strncmp(tag, "uid=", 4) == 0)
+			uid = tag + 4;
+		else {		/* bad format */
+			err = 1;
+			break;
+		}
+		datap += taglen + 1;
+	}
+
+	if (!err) {
+		ima_info("%s subj: %s %s %s obj: %s %s %s %s %s %s %s\n",
+			 action ? "measure " : "dont_measure",
+			 subj_user, subj_role, subj_type,
+			 obj_user, obj_role, obj_type,
+			 func, mask, fsmagic, uid);
+		ima_add_rule(action, subj_user, subj_role, subj_type,
+			     obj_user, obj_role, obj_type,
+			     func, mask, fsmagic, uid);
+	}
+out:
+	if (!data)
+		kfree(data);
+	return rc;
+}
+
+static struct dentry *ima_dir;
+static struct dentry *binary_runtime_measurements;
+static struct dentry *ascii_runtime_measurements;
+static struct dentry *runtime_measurements_count;
+static struct dentry *violations;
+static struct dentry *ima_policy;
+
+static int ima_release_policy(struct inode *inode, struct file *file)
+{
+	ima_update_policy();
+	securityfs_remove(ima_policy);
+	ima_policy = NULL;
+	return 0;
+}
+
+static struct file_operations ima_measure_policy_ops = {
+	.write = ima_write_policy,
+	.release = ima_release_policy
+};
+
+int ima_fs_init(void)
+{
+	ima_dir = securityfs_create_dir("ima", NULL);
+	if (!ima_dir || IS_ERR(ima_dir))
+		return -1;
+
+	binary_runtime_measurements =
+	    securityfs_create_file("binary_runtime_measurements",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_measurements_ops);
+	if (!binary_runtime_measurements || IS_ERR(binary_runtime_measurements))
+		goto out;
+
+	ascii_runtime_measurements =
+	    securityfs_create_file("ascii_runtime_measurements",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_ascii_measurements_ops);
+	if (!ascii_runtime_measurements || IS_ERR(ascii_runtime_measurements))
+		goto out;
+
+	runtime_measurements_count =
+	    securityfs_create_file("runtime_measurements_count",
+				   S_IRUSR | S_IRGRP, ima_dir, NULL,
+				   &ima_measurements_count_ops);
+	if (!runtime_measurements_count || IS_ERR(runtime_measurements_count))
+		goto out;
+
+	violations =
+	    securityfs_create_file("violations", S_IRUSR | S_IRGRP,
+				   ima_dir, NULL, &ima_htable_violations_ops);
+	if (!violations || IS_ERR(violations))
+		goto out;
+
+	ima_policy = securityfs_create_file("policy",
+					    S_IRUSR | S_IRGRP | S_IWUSR,
+					    ima_dir, NULL,
+					    &ima_measure_policy_ops);
+	ima_init_policy();
+	return 0;
+
+out:
+	securityfs_remove(runtime_measurements_count);
+	securityfs_remove(ascii_runtime_measurements);
+	securityfs_remove(binary_runtime_measurements);
+	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
+	return -1;
+}
+
+void __exit ima_fs_cleanup(void)
+{
+	securityfs_remove(violations);
+	securityfs_remove(runtime_measurements_count);
+	securityfs_remove(ascii_runtime_measurements);
+	securityfs_remove(binary_runtime_measurements);
+	securityfs_remove(ima_dir);
+	securityfs_remove(ima_policy);
+}
Index: security-testing-2.6/security/integrity/ima/ima_init.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_init.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer      <sailer@watson.ibm.com>
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * 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.
+ *
+ * File: ima_init.c
+ *             initialization and cleanup functions
+ */
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include "ima.h"
+
+/* name for boot aggregate entry */
+static char *boot_aggregate_name = "boot_aggregate";
+static const char version[] = "v7.6 02/27/2007";
+
+int ima_used_chip;
+
+static void ima_add_boot_aggregate(void)
+{
+	/* cumulative sha1 over tpm registers 0-7 */
+	struct ima_measure_entry *entry;
+	size_t count;
+	int err;
+
+	/* create new entry for boot aggregate */
+	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+	if (entry == NULL) {
+		ima_add_violation(NULL, boot_aggregate_name,
+				  "add_measure", "ENOMEM");
+		return;
+	}
+	count = strlen(boot_aggregate_name);
+	if (count > IMA_EVENT_NAME_LEN_MAX)
+		count = IMA_EVENT_NAME_LEN_MAX;
+	memcpy(entry->template_name, boot_aggregate_name, count);
+	entry->template_name[count] = '\0';
+	if (ima_used_chip) {
+		int i;
+		u8 pcr_i[20];
+		struct hash_desc desc;
+		struct crypto_hash *tfm;
+		struct scatterlist sg;
+
+		tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
+		if (!tfm || IS_ERR(tfm)) {
+			kfree(entry);
+			ima_error("error initializing digest.\n");
+			return;
+		}
+		desc.tfm = tfm;
+		desc.flags = 0;
+		crypto_hash_init(&desc);
+
+		for (i = 0; i < 8; i++) {
+			ima_pcrread(i, pcr_i, sizeof(pcr_i));
+			/* now accumulate with current aggregate */
+			sg_init_one(&sg, (u8 *) pcr_i, 20);
+			crypto_hash_update(&desc, &sg, 20);
+		}
+		crypto_hash_final(&desc, entry->digest);
+		crypto_free_hash(tfm);
+	} else
+		memset(entry->digest, 0xff, 20);
+
+	/* now add measurement; if TPM bypassed, we have a ff..ff entry */
+	err = ima_add_measure_entry(entry, 0);
+	if (err < 0) {
+		kfree(entry);
+		ima_add_violation(NULL, boot_aggregate_name,
+				  "add_measure", " ");
+	}
+}
+
+int ima_init(void)
+{
+	int rc;
+
+	ima_used_chip = 0;
+	rc = tpm_pcr_read(IMA_TPM, 0, NULL);
+	if (rc == 0)
+		ima_used_chip = 1;
+
+	if (!ima_used_chip)
+		ima_info("No TPM chip found(rc = %d), activating TPM-bypass!\n",
+			 rc);
+
+	ima_create_htable();	/* for measurements */
+	ima_add_boot_aggregate();	/* boot aggregate must be first entry */
+
+	return ima_fs_init();
+}
+
+void __exit ima_cleanup(void)
+{
+	ima_fs_cleanup();
+}
Index: security-testing-2.6/security/integrity/ima/ima_main.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_main.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Serge Hallyn <serue@us.ibm.com>
+ * Kylene Hall <kylene@us.ibm.com>
+ * 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.
+ *
+ * File: ima_main.c
+ *             implements the IMA LIM hooks
+ */
+#include <linux/module.h>
+#include <linux/integrity.h>
+#include <linux/magic.h>
+#include <linux/writeback.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/audit.h>
+#include <linux/ima.h>
+#include <linux/mman.h>
+#include <linux/namei.h>
+
+#include "ima.h"
+
+static bool ima_initialized = false;
+char *ima_hash = "sha1";
+static int __init hash_setup(char *str)
+{
+	char *op = "setup";
+	char *hash = "sha1";
+
+	if (strncmp(str, "md5", 3) == 0) {
+		op = "setup";
+		hash = "md5";
+		ima_hash = str;
+	} else if (strncmp(str, "sha1", 4) != 0) {
+		op = "hash_setup";
+		hash = "invalid_hash_type";
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash, 0);
+	return 1;
+}
+
+__setup("ima_hash=", hash_setup);
+
+/* For use when the LSM module makes LIM API calls */
+#ifdef CONFIG_IMA_BASE_HOOKS
+static int ima_base_hooks = 1;
+#else
+static int ima_base_hooks;
+#endif
+
+/*
+ * Setup the data structure used for the IMA LIM API calls.
+ */
+void ima_fixup_argsdata(struct ima_args_data *data, struct file *file,
+			struct path *path, int mask, int function)
+{
+	struct dentry *dentry = NULL;
+
+	data->file = file;
+	data->path = path;
+	data->mask = mask;
+	data->function = function;
+
+	if (file && file->f_dentry) {
+		data->dentry = dentry = file->f_dentry;
+	}
+	if (path && path->dentry) {
+		if (!dentry)
+			data->dentry = dentry = path->dentry;
+	}
+	if (dentry && dentry->d_inode) {
+		data->inode = dentry->d_inode;
+	}
+
+	return;
+}
+
+/**
+ * ima_file_free - called on close
+ * @file: pointer to file being closed
+ *
+ * Flag files that changed, based on i_version.
+ */
+static void ima_file_free(struct file *file)
+{
+	struct inode *inode = NULL;
+	struct ima_iint_cache *iint;
+
+	if (!file->f_dentry)	/* can be NULL */
+		return;
+
+	inode = file->f_dentry->d_inode;
+	if (S_ISDIR(inode->i_mode))
+		return;
+	if ((file->f_mode & FMODE_WRITE) &&
+	    (atomic_read(&inode->i_writecount) == 1)) {
+		iint = inode->i_integrity;
+		mutex_lock(&iint->mutex);
+		if (iint->version != inode->i_version)
+			iint->measured = 0;
+		mutex_unlock(&iint->mutex);
+	}
+}
+
+/**
+ * ima_alloc_integrity - allocate and attach an integrity structure
+ * @inode: the inode structure
+ *
+ * Returns 0 on success, -ENOMEM on failure
+ */
+static int ima_inode_alloc_integrity(struct inode *inode)
+{
+	struct ima_iint_cache *iint;
+
+	iint = kzalloc(sizeof(*iint), GFP_KERNEL);
+	if (!iint)
+		return -ENOMEM;
+
+	mutex_init(&iint->mutex);
+	inode->i_integrity = iint;
+	iint->version = inode->i_version;
+	return 0;
+}
+
+/**
+ * ima_inode_free_integrity - free the integrity structure
+ * @inode: the inode structure
+ */
+static void ima_inode_free_integrity(struct inode *inode)
+{
+	struct ima_iint_cache *iint = inode->i_integrity;
+
+	if (iint) {
+		inode->i_integrity = NULL;
+		kfree(iint);
+	}
+}
+
+/**
+ * ima_inode_permission - based on policy, collect/store measurement.
+ * @file: pointer to the file to be measured
+ * @path: pointer to a path structure containing the inode to be measured
+ * @mask: contains MAY_READ, MAY_WRITE, MAY_APPEND or MAY_EXECUTE
+ *
+ * Measure files being open for read, based on the ima_must_measure()
+ * policy decision.
+ *
+ * Invalidate the PCR:
+ * 	- Opening a file for write when already open for read,
+ *	  results in a time of measure, time of use (ToMToU) error.
+ *	- Opening a file for read when already open for write,
+ * 	  could result in a file measurement error.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+static int ima_inode_permission(struct file *file, struct path *path, int mask)
+{
+	struct ima_data idata;
+	struct ima_args_data *data = &idata.data.args;
+	struct dentry *dentry;
+	struct inode *inode;
+
+	if (!ima_initialized)
+		return 0;
+
+	memset(&idata, 0, sizeof idata);
+	ima_fixup_argsdata(data, file, path, mask, INODE_PERMISSION);
+	inode = data->inode;
+
+	/* The file name is only a hint. */
+	dentry = file ? file->f_dentry : path->dentry;
+	data->filename = (!dentry->d_name.name) ? (char *)dentry->d_iname :
+	    (char *)dentry->d_name.name;
+
+	/* Invalidate PCR, if a measured file is already open for read */
+	if ((mask == MAY_WRITE) || (mask == MAY_APPEND)) {
+		int mask_sav = data->mask;
+		int rc;
+
+		data->mask = MAY_READ;
+		rc = ima_must_measure(&idata);
+		if (!rc) {
+			if (atomic_read(&(data->dentry->d_count)) - 1 >
+			    atomic_read(&(inode->i_writecount)))
+				ima_add_violation(inode, data->filename,
+						  "invalid_pcr", "ToMToU");
+		}
+		data->mask = mask_sav;
+		goto out;
+	}
+
+	/* measure executables later */
+	if (mask & MAY_READ) {
+		int rc;
+
+		rc = ima_must_measure(&idata);
+		if (!rc) {
+			/* Invalidate PCR, if a measured file is
+			 * already open for write.
+			 */
+			if (atomic_read(&(inode->i_writecount)) > 0)
+				ima_add_violation(inode, data->filename,
+						  "invalid_pcr",
+						  "open_writers");
+
+			idata.type = IMA_DATA;
+			rc = ima_collect_measurement(&idata);
+			if (!rc)
+				ima_store_measurement(&idata);
+		}
+	}
+out:
+	return 0;
+}
+
+/**
+ * ima_file_mmap - based on policy, collect/store measurement.
+ * @file: pointer to the file to be measured
+ * @prot contains the protection that will be applied by the kernel.
+ *
+ * Measure files being mmapped executable based on the ima_must_measure()
+ * policy decision.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+static int ima_file_mmap(struct file *file, unsigned long prot)
+{
+	struct ima_data idata;
+	struct ima_args_data *data = &idata.data.args;
+	int rc = 0;
+
+	if (!ima_initialized)
+		return 0;
+	if (!file || !file->f_dentry)
+		return rc;
+	if (!(prot & VM_EXEC))
+		return rc;
+
+	ima_fixup_argsdata(data, file, NULL, MAY_EXEC, FILE_MMAP);
+	data->filename = (!file->f_dentry->d_name.name) ?
+	    (char *)file->f_dentry->d_iname :
+	    (char *)file->f_dentry->d_name.name;
+
+	rc = ima_must_measure(&idata);
+	if (!rc) {
+		idata.type = IMA_DATA;
+		rc = ima_collect_measurement(&idata);
+		if (!rc)
+			ima_store_measurement(&idata);
+	}
+	return 0;
+}
+
+/**
+ * ima_bprm_check_integrity - based on policy, collect/store measurement.
+ * @bprm: contains the linux_binprm structure
+ *
+ * The OS protects against an executable file, already open for write,
+ * from being executed in deny_write_access() and an executable file,
+ * already open for execute, from being modified in get_write_access().
+ * So we can be certain that what we verify and measure here is actually
+ * what is being executed.
+ *
+ * Return 0 on success, an error code on failure.
+ * (Based on the results of appraise_measurement().)
+ */
+static int ima_bprm_check_integrity(struct linux_binprm *bprm)
+{
+	struct ima_data idata;
+	struct ima_args_data *data = &idata.data.args;
+	int rc = 0;
+
+	if (!ima_initialized)
+		return 0;
+	ima_fixup_argsdata(data, bprm->file, NULL, MAY_EXEC, BPRM_CHECK);
+	data->filename = bprm->filename;
+
+	rc = ima_must_measure(&idata);
+	if (!rc) {
+		idata.type = IMA_DATA;
+		rc = ima_collect_measurement(&idata);
+		if (!rc)
+			ima_store_measurement(&idata);
+	}
+	return 0;
+}
+
+static const struct integrity_operations ima_integrity_ops = {
+	.bprm_check_integrity = ima_bprm_check_integrity,
+	.inode_permission = ima_inode_permission,
+	.inode_alloc_integrity = ima_inode_alloc_integrity,
+	.inode_free_integrity = ima_inode_free_integrity,
+	.file_free_integrity = ima_file_free,
+	.file_mmap = ima_file_mmap,
+};
+
+static const struct integrity_operations ima_base_ops = {
+	.inode_alloc_integrity = ima_inode_alloc_integrity,
+	.inode_free_integrity = ima_inode_free_integrity,
+	.file_free_integrity = ima_file_free,
+};
+
+/* Register the integrity ops early so that i_integrity is
+ * allocated at inode initialization.
+ */
+static int __init init_ops(void)
+{
+	int error;
+
+	if (ima_base_hooks)
+		error = register_integrity(&ima_base_ops);
+	else
+		error = register_integrity(&ima_integrity_ops);
+	return error;
+}
+
+/* After the TPM is available, start IMA
+ */
+static int __init init_ima(void)
+{
+	int error;
+
+	error = ima_init();
+	if (error)
+		goto out;
+	ima_initialized = true;
+	integrity_register_template("ima", &ima_template_ops);
+out:
+	return error;
+}
+
+static void __exit cleanup_ima(void)
+{
+	integrity_unregister_template("ima");
+	unregister_integrity(&ima_integrity_ops);
+	ima_cleanup();
+}
+
+security_initcall(init_ops);	/* Register the integrity ops early */
+late_initcall(init_ima);	/* Start IMA after the TPM is available */
+module_exit(cleanup_ima);
+
+MODULE_DESCRIPTION("Integrity Measurement Architecture");
+MODULE_LICENSE("GPL");
Index: security-testing-2.6/security/integrity/ima/ima_policy.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_policy.c
@@ -0,0 +1,330 @@
+/*
+ * 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.
+ *
+ * ima_policy.c
+ * 	- initialize default measure policy rules
+	- load a policy ruleset
+ *
+ */
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/audit.h>
+#include <linux/security.h>
+#include <linux/integrity.h>
+#include <linux/magic.h>
+
+#include "ima.h"
+
+#define MAX_LSM_RULES 6
+enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
+	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
+};
+
+#define audit_type(type) AUDIT_ ##type
+#define lsm_type(type) LSM_ ##type
+
+struct ima_measure_rule_entry {
+	struct list_head list;
+	int action;
+	struct {
+		void *rule;
+		int type;	/* audit type */
+	} lsm_field[MAX_LSM_RULES];
+	uint flags;
+	enum lim_hooks func;
+	int mask;
+	ulong fsmagic;
+	uid_t uid;
+};
+
+/* flags definitions */
+#define IMA_FUNC 	0x0001
+#define IMA_MASK 	0x0002
+#define IMA_FSMAGIC	0x0004
+#define IMA_UID		0x0008
+
+/* Without LSM specific knowledge, default policy can only
+ * be written in terms of .action, .func, .mask and .fsmagic.
+ */
+static struct ima_measure_rule_entry default_rules[] = {
+	{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
+	{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
+	 .flags = IMA_FSMAGIC},
+	{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
+	 .flags = IMA_FUNC | IMA_MASK},
+	{.action = MEASURE,.func = INODE_PERMISSION,.mask = MAY_READ,.uid = 0,
+	 .flags = IMA_FUNC | IMA_MASK | IMA_UID}
+};
+
+static struct list_head measure_default_rules;
+static struct list_head measure_policy_rules;
+static struct list_head *ima_measure;
+
+static DEFINE_MUTEX(ima_measure_mutex);
+
+/**
+ * ima_match_rules - determine whether an inode matches the measure rule.
+ * @rule: a pointer to a rule
+ * @inode: a pointer to an inode
+ * @func: LIM hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Returns true on rule match, false on failure.
+ */
+static bool ima_match_rules(struct ima_measure_rule_entry *rule,
+			    struct inode *inode, enum lim_hooks func, int mask)
+{
+	struct task_struct *tsk = current;
+	int i;
+
+	if ((rule->flags & IMA_FUNC) && rule->func != func)
+		return false;
+	if ((rule->flags & IMA_MASK) && rule->mask != mask)
+		return false;
+	if ((rule->flags & IMA_FSMAGIC)
+	    && rule->fsmagic != inode->i_sb->s_magic)
+		return false;
+	if ((rule->flags & IMA_UID) && rule->uid != tsk->uid)
+		return false;
+	for (i = 0; i < MAX_LSM_RULES; i++) {
+		int rc;
+		u32 osid, sid;
+
+		if (!rule->lsm_field[i].rule)
+			continue;
+
+		switch (i) {
+		case LSM_OBJ_USER:
+		case LSM_OBJ_ROLE:
+		case LSM_OBJ_TYPE:
+			security_inode_getsecid(inode, &osid);
+			rc = security_filter_rule_match(osid,
+							rule->lsm_field[i].type,
+							AUDIT_EQUAL,
+							rule->lsm_field[i].rule,
+							NULL);
+			break;
+		case LSM_SUBJ_USER:
+		case LSM_SUBJ_ROLE:
+		case LSM_SUBJ_TYPE:
+			security_task_getsecid(tsk, &sid);
+			rc = security_filter_rule_match(sid,
+							rule->lsm_field[i].type,
+							AUDIT_EQUAL,
+							rule->lsm_field[i].rule,
+							NULL);
+		default:
+			break;
+		}
+		if (!rc)
+			return false;
+	}
+	return true;
+}
+
+/**
+ * ima_match_policy - decision based on LSM and other conditions
+ * @inode: pointer to an inode
+ * @func: IMA hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ *
+ * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
+ * conditions. Returns rule action on rule match, 0 on failure.
+ */
+int ima_match_policy(struct inode *inode, enum lim_hooks func, int mask)
+{
+	struct ima_measure_rule_entry *entry;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(entry, ima_measure, list) {
+		bool rc;
+
+		rc = ima_match_rules(entry, inode, func, mask);
+		if (rc) {
+			rcu_read_unlock();
+			return entry->action;
+		}
+	}
+	rcu_read_unlock();
+	return 0;
+}
+
+/**
+ * ima_init_policy - initialize the default and policy measure rules.
+ */
+void ima_init_policy(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&measure_default_rules);
+	for (i = 0; i < ARRAY_SIZE(default_rules); i++)
+		list_add_tail(&default_rules[i].list, &measure_default_rules);
+	ima_measure = &measure_default_rules;
+
+	INIT_LIST_HEAD(&measure_policy_rules);
+}
+
+/**
+ * ima_update_policy - update default_rules with new measure rules
+ *
+ * Wait to update the default rules with a complete new set of measure rules.
+ */
+void ima_update_policy(void)
+{
+	char *op = "policy_update";
+	char *cause = "already exists";
+	int result = 1;
+
+	if (ima_measure == &measure_default_rules) {
+		ima_measure = &measure_policy_rules;
+		cause = "complete";
+		result = 0;
+	}
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+			    NULL, op, cause, result);
+}
+
+/**
+ * ima_add_rule - add ima measure rules
+ * @action: integer 1 indicating MEASURE, 0 indicating DONT_MEASURE
+ * @subj: pointer to an LSM subject value
+ * @obj:  pointer to an LSM object value
+ * @type:  pointer to an LSM object type value
+ * @func: LIM hook identifier
+ * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
+ * @fsmagic: fs magic hex value string
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int ima_add_rule(int action,
+		 char *subj_user, char *subj_role, char *subj_type,
+		 char *obj_user, char *obj_role, char *obj_type,
+		 char *func, char *mask, char *fsmagic, char *uid)
+{
+	struct ima_measure_rule_entry *entry;
+	int i, result = 0;
+
+	/* Prevent installed policy from changing */
+	if (ima_measure != &measure_default_rules) {
+		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
+				    NULL, "policy_update", "already exists", 1);
+		return -EACCES;
+	}
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	INIT_LIST_HEAD(&entry->list);
+	if (action < 0 || action > 1)
+		result = -EINVAL;
+	else
+		entry->action = action;
+
+	if (!result && subj_user) {
+		i = lsm_type(SUBJ_USER);
+		entry->lsm_field[i].type = audit_type(SUBJ_USER);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, subj_user,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && subj_role) {
+		i = lsm_type(SUBJ_ROLE);
+		entry->lsm_field[i].type = audit_type(SUBJ_ROLE);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, subj_role,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && subj_type) {
+		i = lsm_type(SUBJ_TYPE);
+		entry->lsm_field[i].type = audit_type(SUBJ_TYPE);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, subj_type,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && obj_user) {
+		i = lsm_type(OBJ_USER);
+		entry->lsm_field[i].type = audit_type(OBJ_USER);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, obj_user,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && obj_role) {
+		i = lsm_type(OBJ_ROLE);
+		entry->lsm_field[i].type = audit_type(OBJ_ROLE);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, obj_role,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && obj_type) {
+		i = lsm_type(OBJ_TYPE);
+		entry->lsm_field[i].type = audit_type(OBJ_TYPE);
+		result = security_filter_rule_init(entry->lsm_field[i].type,
+						   AUDIT_EQUAL, obj_type,
+						   &entry->lsm_field[i].rule);
+	}
+	if (!result && func) {
+		if (strcmp(func, "INODE_PERMISSION") == 0)
+			entry->func = INODE_PERMISSION;
+		else if (strcmp(func, "FILE_MMAP") == 0)
+			entry->func = FILE_MMAP;
+		else if (strcmp(func, "BPRM_CHECK") == 0)
+			entry->func = BPRM_CHECK;
+		else
+			result = -EINVAL;
+		if (!result)
+			entry->flags |= IMA_FUNC;
+	}
+	if (!result && mask) {
+		if (strcmp(mask, "MAY_EXEC") == 0)
+			entry->mask = MAY_EXEC;
+		else if (strcmp(mask, "MAY_WRITE") == 0)
+			entry->mask = MAY_WRITE;
+		else if (strcmp(mask, "MAY_READ") == 0)
+			entry->mask = MAY_READ;
+		else if (strcmp(mask, "MAY_APPEND") == 0)
+			entry->mask = MAY_APPEND;
+		else
+			result = -EINVAL;
+		if (!result)
+			entry->flags |= IMA_MASK;
+	}
+	if (!result && fsmagic) {
+		int rc;
+
+		rc = strict_strtoul(fsmagic, 16, &entry->fsmagic);
+		if (rc)
+			result = -EINVAL;
+		else
+			entry->flags |= IMA_FSMAGIC;
+	}
+	if (!result && uid) {
+		int rc;
+		ulong lnum;
+
+		rc = strict_strtoul(uid, 10, &lnum);
+		if (rc)
+			result = -EINVAL;
+		else {
+			entry->uid = (uid_t) lnum;
+			if (entry->uid != lnum)
+				result = -EINVAL;
+			else
+				entry->flags |= IMA_UID;
+		}
+	}
+	if (!result) {
+		mutex_lock(&ima_measure_mutex);
+		list_add_tail(&entry->list, &measure_policy_rules);
+		mutex_unlock(&ima_measure_mutex);
+	}
+	return result;
+}
Index: security-testing-2.6/security/integrity/ima/ima_queue.c
===================================================================
--- /dev/null
+++ security-testing-2.6/security/integrity/ima/ima_queue.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ *
+ * Authors:
+ * Serge Hallyn <serue@us.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * 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.
+ *
+ * File: ima_queue.c
+ *       implements queues that store IMA measurements and
+ *       maintains aggregate over the stored measurements
+ *       in the pre-configured TPM PCR (if available)
+ *       The measurement list is append-only. No entry is
+ *       ever removed or changed during the boot-cycle.
+ */
+#include <linux/module.h>
+
+#include "ima.h"
+
+struct list_head ima_measurements;	/* list of all measurements */
+struct ima_h_table ima_htable;	/* key: inode (before secure-hashing a file) */
+
+/* mutex protects atomicity of extending measurement list
+ * and extending the TPM PCR aggregate. Since tpm_extend can take
+ * long (and the tpm driver uses a mutex), we can't use the spinlock.
+ */
+static DEFINE_MUTEX(ima_extend_list_mutex);
+
+void ima_create_htable(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&ima_measurements);
+	atomic_set(&ima_htable.len, 0);
+	atomic_long_set(&ima_htable.violations, 0);
+	ima_htable.max_htable_size = IMA_MEASURE_HTABLE_SIZE;
+
+	for (i = 0; i < ima_htable.max_htable_size; i++) {
+		INIT_HLIST_HEAD(&ima_htable.queue[i]);
+		atomic_set(&ima_htable.queue_len[i], 0);
+	}
+}
+
+struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value)
+{
+	struct ima_queue_entry *qe, *ret = NULL;
+	unsigned int key;
+	struct hlist_node *pos;
+
+	key = IMA_HASH_KEY(digest_value);
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) {
+		if (memcmp(qe->entry->digest, digest_value, 20) == 0) {
+			ret = qe;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+/* Called with mutex held */
+static int ima_add_digest_entry(struct ima_measure_entry *entry)
+{
+	struct ima_queue_entry *qe;
+	unsigned int key;
+
+	key = IMA_HASH_KEY(entry->digest);
+	qe = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (qe == NULL) {
+		ima_error("OUT OF MEMORY ERROR creating queue entry.\n");
+		return -ENOMEM;
+	}
+	qe->entry = entry;
+
+	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+	atomic_inc(&ima_htable.queue_len[key]);
+	return 0;
+}
+
+int ima_add_measure_entry(struct ima_measure_entry *entry, int violation)
+{
+	struct ima_queue_entry *qe;
+	int error = 0;
+
+	mutex_lock(&ima_extend_list_mutex);
+	if (!violation) {
+		if (ima_lookup_digest_entry(entry->digest)) {
+			error = -EEXIST;
+			goto out;
+		}
+	}
+	qe = kmalloc(sizeof(struct ima_queue_entry), GFP_KERNEL);
+	if (qe == NULL) {
+		ima_error("OUT OF MEMORY in %s.\n", __func__);
+		error = -ENOMEM;
+		goto out;
+	}
+	qe->entry = entry;
+
+	INIT_LIST_HEAD(&qe->later);
+	list_add_tail_rcu(&qe->later, &ima_measurements);
+
+	atomic_long_inc(&ima_htable.len);
+	if (ima_add_digest_entry(entry)) {
+		error = -ENOMEM;
+		goto out;
+	}
+	if (violation) {	/* Replace 0x00 with 0xFF */
+		u8 digest[IMA_DIGEST_SIZE];
+
+		memset(digest, 0xff, sizeof digest);
+		ima_extend(digest);
+	} else
+		ima_extend(entry->digest);
+out:
+	mutex_unlock(&ima_extend_list_mutex);
+	return error;
+}

-- 


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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 18:55 ` [PATCH 2/4] integrity: special fs magic Mimi Zohar
@ 2008-08-08 19:04   ` Greg KH
  2008-08-08 19:15     ` Greg KH
  2008-08-08 19:36     ` Mimi Zohar
  2008-08-08 23:15   ` Christoph Hellwig
  1 sibling, 2 replies; 47+ messages in thread
From: Greg KH @ 2008-08-08 19:04 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, zohar

On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
>     - Move special fs magic number definitions to magic.h
>     - Add magic.h include
>     
>     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>

Why?  What is this patch for?  Are you going to do something with these
magic values later?

thanks,

greg k-h

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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 19:04   ` Greg KH
@ 2008-08-08 19:15     ` Greg KH
  2008-08-08 19:50       ` Mimi Zohar
  2008-08-09 18:47       ` Christoph Hellwig
  2008-08-08 19:36     ` Mimi Zohar
  1 sibling, 2 replies; 47+ messages in thread
From: Greg KH @ 2008-08-08 19:15 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, zohar

On Fri, Aug 08, 2008 at 12:04:48PM -0700, Greg KH wrote:
> On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> >     - Move special fs magic number definitions to magic.h
> >     - Add magic.h include
> >     
> >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> 
> Why?  What is this patch for?  Are you going to do something with these
> magic values later?

Ok, I now see the follow-up patch that does something with them.

You should say so in this patch.

And is it really ok to be doing things from userspace based on a
filesystem "magic" key?  Those are numbers we have never exported to
userspace before, what happens if they are changed?

thanks,

greg k-h

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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 19:04   ` Greg KH
  2008-08-08 19:15     ` Greg KH
@ 2008-08-08 19:36     ` Mimi Zohar
  1 sibling, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 19:36 UTC (permalink / raw)
  To: Greg KH
  Cc: James Morris, linux-kernel, linux-security-module,
	linux-security-module-owner, Randy Dunlap, safford, sailer,
	Stephen Smalley, serue, Al Viro, Mimi Zohar

linux-security-module-owner@vger.kernel.org wrote on 08/08/2008 03:04:48 
PM:


> Re: [PATCH 2/4] integrity: special fs magic
> 
> On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> >     - Move special fs magic number definitions to magic.h
> >     - Add magic.h include
> > 
> >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> 
> Why?  What is this patch for?  Are you going to do something with these
> magic values later?
> 
> thanks,
> 

yes, [PATCH 4/4] integrity: IMA as an integrity service provider,
uses these definition in defining the default IMA measurement policy.
The default policy can be replaced with an LSM specific one.  More
details on the IMA measurement policy are available in 
Documentation/ABI/testing/ima_policy.

Mimi




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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 19:15     ` Greg KH
@ 2008-08-08 19:50       ` Mimi Zohar
  2008-08-08 23:07         ` Greg KH
  2008-08-09 18:47       ` Christoph Hellwig
  1 sibling, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-08 19:50 UTC (permalink / raw)
  To: Greg KH
  Cc: James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, serue, Al Viro, Mimi Zohar

Greg KH <greg@kroah.com> wrote on 08/08/2008 03:15:19 PM:

> On Fri, Aug 08, 2008 at 12:04:48PM -0700, Greg KH wrote:
> > On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> > >     - Move special fs magic number definitions to magic.h
> > >     - Add magic.h include
> > > 
> > >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> > 
> > Why?  What is this patch for?  Are you going to do something with 
these
> > magic values later?
> 
> Ok, I now see the follow-up patch that does something with them.
> 
> You should say so in this patch.
> 
> And is it really ok to be doing things from userspace based on a
> filesystem "magic" key?  Those are numbers we have never exported to
> userspace before, what happens if they are changed?
> 
> thanks,
> 
> greg k-h

Userspace only loads the measurement policy (via securityfs), and if
a magic number changes, and the policy is not updated to match, then
we would end up measuring some filesystems we didn't need to.  Before 
the magic numbers were hard coded in IMA, now at least, it's extensible. 

Mimi

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

* Re: [PATCH 4/4] integrity: IMA as an integrity service provider
  2008-08-08 18:56 ` [PATCH 4/4] integrity: IMA as an integrity service provider Mimi Zohar
@ 2008-08-08 20:06   ` Randy Dunlap
  0 siblings, 0 replies; 47+ messages in thread
From: Randy Dunlap @ 2008-08-08 20:06 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, safford, serue, sailer, zohar

On Fri, 08 Aug 2008 14:56:36 -0400 Mimi Zohar wrote:

> Index: security-testing-2.6/Documentation/kernel-parameters.txt
> ===================================================================
> --- security-testing-2.6.orig/Documentation/kernel-parameters.txt
> +++ security-testing-2.6/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.
>  	INTEGRITY Integrity support is enabled.
>  	IOSCHED	More than one I/O scheduler is enabled.
>  	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
> @@ -862,6 +863,10 @@ and is between 256 and 4096 characters. 
>  	ihash_entries=	[KNL]
>  			Set number of hash buckets for inode cache.
>  
> +	ima_hash=	[IMA] runtime ability to define hash crypto alg.

Please spell out algorithm.

> +			Format: { "MD5" | "SHA1" }
> +			Default is "SHA1".
> +
>  	in2000=		[HW,SCSI]
>  			See header of drivers/scsi/in2000.c.
>  
> Index: security-testing-2.6/security/integrity/ima/Kconfig
> ===================================================================
> --- /dev/null
> +++ security-testing-2.6/security/integrity/ima/Kconfig
> @@ -0,0 +1,48 @@
> +#
> +# IBM Integrity Measurement Architecture
> +#
> +
> +config IMA
> +	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
> +	select TCG_TIS
> +	help
> +	  The Trusted Computing Group(TCG) runtime Integrity
> +	  Measurement Architecture(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_MEASURE_PCR_IDX
> +	int "PCR for Aggregate (8<= Index <= 14)"

Use consistent spacing (8 <= Index <= 14).

> +	depends on IMA
> +	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
> +	default n
> +	help
> +	  Enable this option to allow the LSM module to enforce integrity.
> +
> +config IMA_LSM_RULES
> +	bool "Enable LSM measurement policy rules"
> +	depends on IMA && (SELINUX || SMACK)
> +	default y
> +	help
> +	  Disabling this option will not enforce LSM based policy rules.


---
~Randy
Linux Plumbers Conference, 17-19 September 2008, Portland, Oregon USA
http://linuxplumbersconf.org/

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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 19:50       ` Mimi Zohar
@ 2008-08-08 23:07         ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2008-08-08 23:07 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, serue, Al Viro, Mimi Zohar

On Fri, Aug 08, 2008 at 03:50:02PM -0400, Mimi Zohar wrote:
> Greg KH <greg@kroah.com> wrote on 08/08/2008 03:15:19 PM:
> 
> > On Fri, Aug 08, 2008 at 12:04:48PM -0700, Greg KH wrote:
> > > On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> > > >     - Move special fs magic number definitions to magic.h
> > > >     - Add magic.h include
> > > > 
> > > >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> > > 
> > > Why?  What is this patch for?  Are you going to do something with 
> these
> > > magic values later?
> > 
> > Ok, I now see the follow-up patch that does something with them.
> > 
> > You should say so in this patch.
> > 
> > And is it really ok to be doing things from userspace based on a
> > filesystem "magic" key?  Those are numbers we have never exported to
> > userspace before, what happens if they are changed?
> > 
> > thanks,
> > 
> > greg k-h
> 
> Userspace only loads the measurement policy (via securityfs), and if
> a magic number changes, and the policy is not updated to match, then
> we would end up measuring some filesystems we didn't need to.  Before 
> the magic numbers were hard coded in IMA, now at least, it's extensible. 

Why not just use a name then instead?  That way if the number changes
within the kernel, then it will always be right.

thanks,

greg k-h

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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 18:55 ` [PATCH 2/4] integrity: special fs magic Mimi Zohar
  2008-08-08 19:04   ` Greg KH
@ 2008-08-08 23:15   ` Christoph Hellwig
  1 sibling, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-08 23:15 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, zohar

On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
>     - Move special fs magic number definitions to magic.h
>     - Add magic.h include

Moving them is fine, using them for anything however is not.


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-08 18:55 ` [PATCH 1/4] integrity: TPM internel kernel interface Mimi Zohar
@ 2008-08-09 18:46   ` Christoph Hellwig
  2008-08-11 21:13     ` Mimi Zohar
  0 siblings, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-09 18:46 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, zohar

> +{
> +	struct tpm_chip *pos;
> +
> +	spin_lock(&driver_lock);
> +	list_for_each_entry(pos, &tpm_chip_list, list) {
> +		if ((chip_num == TPM_ANY_NUM || pos->dev_num == chip_num)
> +		    && (chip_typ == TPM_ANY_TYPE)) {
> +			spin_unlock(&driver_lock);
> +			return pos;
> +		}
> +	}
> +
> +	spin_unlock(&driver_lock);

besides the usual coding style issues, what protects the chip from going
away afer you dropped the lock?


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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-08 19:15     ` Greg KH
  2008-08-08 19:50       ` Mimi Zohar
@ 2008-08-09 18:47       ` Christoph Hellwig
  2008-08-10 13:48         ` Mimi Zohar
  1 sibling, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-09 18:47 UTC (permalink / raw)
  To: Greg KH
  Cc: Mimi Zohar, linux-kernel, linux-security-module, Al Viro,
	Stephen Smalley, James Morris, Randy Dunlap, safford, serue,
	sailer, zohar

On Fri, Aug 08, 2008 at 12:15:19PM -0700, Greg KH wrote:
> On Fri, Aug 08, 2008 at 12:04:48PM -0700, Greg KH wrote:
> > On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> > >     - Move special fs magic number definitions to magic.h
> > >     - Add magic.h include
> > >     
> > >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> > 
> > Why?  What is this patch for?  Are you going to do something with these
> > magic values later?
> 
> Ok, I now see the follow-up patch that does something with them.
> 
> You should say so in this patch.
> 
> And is it really ok to be doing things from userspace based on a
> filesystem "magic" key?  Those are numbers we have never exported to
> userspace before, what happens if they are changed?

These constants re exported to userspace in struct statfs .type and
better don't change.  Providing the symbolic names for them sounds
like a good idea to me.  What userspace does with that or not is
their business, and if it's utterly stupid it'll be their fault if
it doesn't work as expected..

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-08 18:56 ` [PATCH 3/4] integrity: Linux Integrity Module(LIM) Mimi Zohar
@ 2008-08-09 18:53   ` Christoph Hellwig
  2008-08-10 13:52     ` Mimi Zohar
  0 siblings, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-09 18:53 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, zohar

> +		if (integrity_inode_alloc(inode)) {
> +			if (inode->i_sb->s_op->destroy_inode)
> +				inode->i_sb->s_op->destroy_inode(inode);
> +			else
> +				kmem_cache_free(inode_cachep, (inode));
> +			return NULL;
> +		}
> +

Please factor this and the lsm failure case out into a single
out_free_inode goto label.


>  int vfs_permission(struct nameidata *nd, int mask)
>  {
> -	return inode_permission(nd->path.dentry->d_inode, mask);
> +	int retval;
> +
> +	retval = inode_permission(nd->path.dentry->d_inode, mask);
> +	if (retval)
> +		return retval;
> +	return integrity_inode_permission(NULL, &nd->path,
> +					  mask & (MAY_READ | MAY_WRITE |
> +						  MAY_EXEC));
>  }
>  
>  /**
> @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
>   */
>  int file_permission(struct file *file, int mask)
>  {
> -	return inode_permission(file->f_path.dentry->d_inode, mask);
> +	int retval;
> +
> +	retval = inode_permission(file->f_path.dentry->d_inode, mask);
> +	if (retval)
> +		return retval;
> +	return integrity_inode_permission(file, NULL,
> +					  mask & (MAY_READ | MAY_WRITE |
> +						  MAY_EXEC));

Please put your hook into inode_permission.  Note that in inode
permission and lots of callers there is no path available so don't pass
it.  Please pass the full MAY_FOO mask for new interfaces and do
filtering that won't break if new ones are introduced.


> +#ifdef CONFIG_INTEGRITY
> +	void			*i_integrity;
> +#endif

Sorry, but I don't think we can bloat the inode even further for this.

> +/*
> + * integrity.h

don't bother to mention the filename in the top of file comment.


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

* Re: [PATCH 2/4] integrity: special fs magic
  2008-08-09 18:47       ` Christoph Hellwig
@ 2008-08-10 13:48         ` Mimi Zohar
  0 siblings, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-10 13:48 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Greg KH, James Morris, linux-kernel, linux-security-module,
	Randy Dunlap, safford, sailer, Stephen Smalley, serue, Al Viro,
	Mimi Zohar

Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:47:59 PM:

 
> On Fri, Aug 08, 2008 at 12:15:19PM -0700, Greg KH wrote:
> > On Fri, Aug 08, 2008 at 12:04:48PM -0700, Greg KH wrote:
> > > On Fri, Aug 08, 2008 at 02:55:42PM -0400, Mimi Zohar wrote:
> > > >     - Move special fs magic number definitions to magic.h
> > > >     - Add magic.h include
> > > > 
> > > >     Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
> > > 
> > > Why?  What is this patch for?  Are you going to do something with 
these
> > > magic values later?
> > 
> > Ok, I now see the follow-up patch that does something with them.
> > 
> > You should say so in this patch.
> > 
> > And is it really ok to be doing things from userspace based on a
> > filesystem "magic" key?  Those are numbers we have never exported to
> > userspace before, what happens if they are changed?
> 
> These constants re exported to userspace in struct statfs .type and
> better don't change.  Providing the symbolic names for them sounds
> like a good idea to me.  What userspace does with that or not is
> their business, and if it's utterly stupid it'll be their fault if
> it doesn't work as expected..

ok.

Mimi

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-09 18:53   ` Christoph Hellwig
@ 2008-08-10 13:52     ` Mimi Zohar
  2008-08-11 17:02       ` Serge E. Hallyn
  2008-08-12 19:25       ` Christoph Hellwig
  0 siblings, 2 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-10 13:52 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-kernel, linux-security-module, Al Viro, Stephen Smalley,
	James Morris, Randy Dunlap, safford, serue, sailer, Mimi Zohar

Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:

> > +      if (integrity_inode_alloc(inode)) {
> > +         if (inode->i_sb->s_op->destroy_inode)
> > +            inode->i_sb->s_op->destroy_inode(inode);
> > +         else
> > +            kmem_cache_free(inode_cachep, (inode));
> > +         return NULL;
> > +      }
> > +
> 
> Please factor this and the lsm failure case out into a single
> out_free_inode goto label.

ok

> >  int vfs_permission(struct nameidata *nd, int mask)
> >  {
> > -   return inode_permission(nd->path.dentry->d_inode, mask);
> > +   int retval;
> > +
> > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
> > +   if (retval)
> > +      return retval;
> > +   return integrity_inode_permission(NULL, &nd->path,
> > +                 mask & (MAY_READ | MAY_WRITE |
> > +                    MAY_EXEC));
> >  }
> > 
> >  /**
> > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
> >   */
> >  int file_permission(struct file *file, int mask)
> >  {
> > -   return inode_permission(file->f_path.dentry->d_inode, mask);
> > +   int retval;
> > +
> > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
> > +   if (retval)
> > +      return retval;
> > +   return integrity_inode_permission(file, NULL,
> > +                 mask & (MAY_READ | MAY_WRITE |
> > +                    MAY_EXEC));
> 
> Please put your hook into inode_permission.  Note that in inode
> permission and lots of callers there is no path available so don't pass
> it.  Please pass the full MAY_FOO mask for new interfaces and do
> filtering that won't break if new ones are introduced.
 
We started out with the integrity_inode_permission() hook call in 
inode_permission(), but because of the removal of the nameidata 
parameter in the last merge, based on discussions
http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
the call to integrity_inode_permission() was moved up to the caller,
where either a file or path are available.  Any suggestions?
 
> > +#ifdef CONFIG_INTEGRITY
> > +   void         *i_integrity;
> > +#endif
> 
> Sorry, but I don't think we can bloat the inode even further for this.

The original version of IMA was LSM based, using i_security. Based
on discussions on the LSM mailing list, it was decided that the LSM hooks
were meant only for access control.  During the same time frame, there 
was a lot of work done in stacking LSM modules and i_security, but that
approach was dropped. It was suggested that we define a separate set of
hooks for integrity, which this patch set provides. Caching integrity 
results is an important aspect. Any suggestions in lieu of defining 
i_integrity?

> > +/*
> > + * integrity.h
> 
> don't bother to mention the filename in the top of file comment.
 
ok

Mimi

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-10 13:52     ` Mimi Zohar
@ 2008-08-11 17:02       ` Serge E. Hallyn
  2008-08-11 19:08         ` Mimi Zohar
  2008-08-12 19:27         ` Christoph Hellwig
  2008-08-12 19:25       ` Christoph Hellwig
  1 sibling, 2 replies; 47+ messages in thread
From: Serge E. Hallyn @ 2008-08-11 17:02 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: Christoph Hellwig, linux-kernel, linux-security-module, Al Viro,
	Stephen Smalley, James Morris, Randy Dunlap, safford, serue,
	sailer, Mimi Zohar

Quoting Mimi Zohar (zohar@us.ibm.com):
> Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:
> 
> > > +      if (integrity_inode_alloc(inode)) {
> > > +         if (inode->i_sb->s_op->destroy_inode)
> > > +            inode->i_sb->s_op->destroy_inode(inode);
> > > +         else
> > > +            kmem_cache_free(inode_cachep, (inode));
> > > +         return NULL;
> > > +      }
> > > +
> > 
> > Please factor this and the lsm failure case out into a single
> > out_free_inode goto label.
> 
> ok
> 
> > >  int vfs_permission(struct nameidata *nd, int mask)
> > >  {
> > > -   return inode_permission(nd->path.dentry->d_inode, mask);
> > > +   int retval;
> > > +
> > > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
> > > +   if (retval)
> > > +      return retval;
> > > +   return integrity_inode_permission(NULL, &nd->path,
> > > +                 mask & (MAY_READ | MAY_WRITE |
> > > +                    MAY_EXEC));
> > >  }
> > > 
> > >  /**
> > > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
> > >   */
> > >  int file_permission(struct file *file, int mask)
> > >  {
> > > -   return inode_permission(file->f_path.dentry->d_inode, mask);
> > > +   int retval;
> > > +
> > > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
> > > +   if (retval)
> > > +      return retval;
> > > +   return integrity_inode_permission(file, NULL,
> > > +                 mask & (MAY_READ | MAY_WRITE |
> > > +                    MAY_EXEC));
> > 
> > Please put your hook into inode_permission.  Note that in inode
> > permission and lots of callers there is no path available so don't pass
> > it.  Please pass the full MAY_FOO mask for new interfaces and do
> > filtering that won't break if new ones are introduced.
> 
> We started out with the integrity_inode_permission() hook call in 
> inode_permission(), but because of the removal of the nameidata 
> parameter in the last merge, based on discussions
> http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
> the call to integrity_inode_permission() was moved up to the caller,
> where either a file or path are available.  Any suggestions?

Mimi, can you explain exactly (and concisely) what you are doing with
the pathname?

> > > +#ifdef CONFIG_INTEGRITY
> > > +   void         *i_integrity;
> > > +#endif
> > 
> > Sorry, but I don't think we can bloat the inode even further for this.
> 
> The original version of IMA was LSM based, using i_security. Based
> on discussions on the LSM mailing list, it was decided that the LSM hooks
> were meant only for access control.  During the same time frame, there 
> was a lot of work done in stacking LSM modules and i_security, but that
> approach was dropped. It was suggested that we define a separate set of
> hooks for integrity, which this patch set provides. Caching integrity 
> results is an important aspect. Any suggestions in lieu of defining 
> i_integrity?

The i_integrity is only bloating the inode if LIM is enabled.  Surely
that beats having LIM define its own hash table and locking to track
integrity labels on inodes?  Do you have another suggestion?

Or is the concern about having more #ifdefs in the struct inode
definition?

-serge

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-11 17:02       ` Serge E. Hallyn
@ 2008-08-11 19:08         ` Mimi Zohar
  2008-08-11 19:56           ` Serge E. Hallyn
  2008-08-12 19:27         ` Christoph Hellwig
  1 sibling, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-11 19:08 UTC (permalink / raw)
  To: serue
  Cc: Christoph Hellwig, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, serue, Al Viro, Mimi Zohar

serue@linux.vnet.ibm.com wrote on 08/11/2008 01:02:55 PM:

> Quoting Mimi Zohar (zohar@us.ibm.com):
> > Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:
> > > >  int vfs_permission(struct nameidata *nd, int mask)
> > > >  {
> > > > -   return inode_permission(nd->path.dentry->d_inode, mask);
> > > > +   int retval;
> > > > +
> > > > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
> > > > +   if (retval)
> > > > +      return retval;
> > > > +   return integrity_inode_permission(NULL, &nd->path,
> > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > +                    MAY_EXEC));
> > > >  }
> > > > 
> > > >  /**
> > > > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
> > > >   */
> > > >  int file_permission(struct file *file, int mask)
> > > >  {
> > > > -   return inode_permission(file->f_path.dentry->d_inode, mask);
> > > > +   int retval;
> > > > +
> > > > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
> > > > +   if (retval)
> > > > +      return retval;
> > > > +   return integrity_inode_permission(file, NULL,
> > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > +                    MAY_EXEC));
> > > 
> > > Please put your hook into inode_permission.  Note that in inode
> > > permission and lots of callers there is no path available so don't 
pass
> > > it.  Please pass the full MAY_FOO mask for new interfaces and do
> > > filtering that won't break if new ones are introduced.
> > 
> > We started out with the integrity_inode_permission() hook call in 
> > inode_permission(), but because of the removal of the nameidata 
> > parameter in the last merge, based on discussions
> > http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
> > the call to integrity_inode_permission() was moved up to the caller,
> > where either a file or path are available.  Any suggestions?
> 
> Mimi, can you explain exactly (and concisely) what you are doing with
> the pathname?

IMA maintains a list of hash values of system sensitive files loaded 
into the run-time of the system and extends a PCR with the hash value. 
In order to calculate this hash value, IMA requires access to either
the file or the path, which currently is not accessible in 
inode_permission().

Mimi

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-11 19:08         ` Mimi Zohar
@ 2008-08-11 19:56           ` Serge E. Hallyn
  2008-08-12  8:41             ` Peter Dolding
  2008-08-13 17:03             ` Mimi Zohar
  0 siblings, 2 replies; 47+ messages in thread
From: Serge E. Hallyn @ 2008-08-11 19:56 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: serue, Christoph Hellwig, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, Al Viro, Mimi Zohar

Quoting Mimi Zohar (zohar@us.ibm.com):
> serue@linux.vnet.ibm.com wrote on 08/11/2008 01:02:55 PM:
> 
> > Quoting Mimi Zohar (zohar@us.ibm.com):
> > > Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:
> > > > >  int vfs_permission(struct nameidata *nd, int mask)
> > > > >  {
> > > > > -   return inode_permission(nd->path.dentry->d_inode, mask);
> > > > > +   int retval;
> > > > > +
> > > > > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
> > > > > +   if (retval)
> > > > > +      return retval;
> > > > > +   return integrity_inode_permission(NULL, &nd->path,
> > > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > > +                    MAY_EXEC));
> > > > >  }
> > > > > 
> > > > >  /**
> > > > > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
> > > > >   */
> > > > >  int file_permission(struct file *file, int mask)
> > > > >  {
> > > > > -   return inode_permission(file->f_path.dentry->d_inode, mask);
> > > > > +   int retval;
> > > > > +
> > > > > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
> > > > > +   if (retval)
> > > > > +      return retval;
> > > > > +   return integrity_inode_permission(file, NULL,
> > > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > > +                    MAY_EXEC));
> > > > 
> > > > Please put your hook into inode_permission.  Note that in inode
> > > > permission and lots of callers there is no path available so don't 
> pass
> > > > it.  Please pass the full MAY_FOO mask for new interfaces and do
> > > > filtering that won't break if new ones are introduced.
> > > 
> > > We started out with the integrity_inode_permission() hook call in 
> > > inode_permission(), but because of the removal of the nameidata 
> > > parameter in the last merge, based on discussions
> > > http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
> > > the call to integrity_inode_permission() was moved up to the caller,
> > > where either a file or path are available.  Any suggestions?
> > 
> > Mimi, can you explain exactly (and concisely) what you are doing with
> > the pathname?
> 
> IMA maintains a list of hash values of system sensitive files loaded 
> into the run-time of the system and extends a PCR with the hash value. 
> In order to calculate this hash value, IMA requires access to either
> the file or the path, which currently is not accessible in 
> inode_permission().

So the usual question is, if I've done	
	ln -s /etc/shadow /tmp/shadow
will IMA do the right thing if I'm opening /tmp/shadow?  Or will it only
catch any writes I've done the next time someone (i.e. passwd) opens
/etc/shadow?

thanks,
-serge

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-09 18:46   ` Christoph Hellwig
@ 2008-08-11 21:13     ` Mimi Zohar
  2008-08-12 19:30       ` Christoph Hellwig
  0 siblings, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2008-08-11 21:13 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, serue, Al Viro, Debora Velarde,
	Mimi Zohar, Kenneth Goldman

Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:46:22 PM:

> > +{
> > +   struct tpm_chip *pos;
> > +
> > +   spin_lock(&driver_lock);
> > +   list_for_each_entry(pos, &tpm_chip_list, list) {
> > +      if ((chip_num == TPM_ANY_NUM || pos->dev_num == chip_num)
> > +          && (chip_typ == TPM_ANY_TYPE)) {
> > +         spin_unlock(&driver_lock);
> > +         return pos;
> > +      }
> > +   }
> > +
> > +   spin_unlock(&driver_lock);
> 
> besides the usual coding style issues, what protects the chip from going
> away afer you dropped the lock?
> 

I assume the concern here is that between looking up the chip and actually 

using the chip, the TPM chip is disabled/deactivated.  Based on 
discussions 
with Kenneth Goldman, the TCG main specification part2: structures, 
require
that even if the TPM is disabled/deactivated, the command to extend the 
PCR 
will succeed, but the command to read the PCR will fail with an 
appropriate 
error code.

Mimi

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-11 19:56           ` Serge E. Hallyn
@ 2008-08-12  8:41             ` Peter Dolding
  2008-08-12 19:29               ` Christoph Hellwig
  2008-08-13 17:03             ` Mimi Zohar
  1 sibling, 1 reply; 47+ messages in thread
From: Peter Dolding @ 2008-08-12  8:41 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Mimi Zohar, serue, Christoph Hellwig, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, Al Viro, Mimi Zohar

On Tue, Aug 12, 2008 at 5:56 AM, Serge E. Hallyn <serue@us.ibm.com> wrote:
> Quoting Mimi Zohar (zohar@us.ibm.com):
>> serue@linux.vnet.ibm.com wrote on 08/11/2008 01:02:55 PM:
>>
>> > Quoting Mimi Zohar (zohar@us.ibm.com):
>> > > Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:
>> > > > >  int vfs_permission(struct nameidata *nd, int mask)
>> > > > >  {
>> > > > > -   return inode_permission(nd->path.dentry->d_inode, mask);
>> > > > > +   int retval;
>> > > > > +
>> > > > > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
>> > > > > +   if (retval)
>> > > > > +      return retval;
>> > > > > +   return integrity_inode_permission(NULL, &nd->path,
>> > > > > +                 mask & (MAY_READ | MAY_WRITE |
>> > > > > +                    MAY_EXEC));
>> > > > >  }
>> > > > >
>> > > > >  /**
>> > > > > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
>> > > > >   */
>> > > > >  int file_permission(struct file *file, int mask)
>> > > > >  {
>> > > > > -   return inode_permission(file->f_path.dentry->d_inode, mask);
>> > > > > +   int retval;
>> > > > > +
>> > > > > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
>> > > > > +   if (retval)
>> > > > > +      return retval;
>> > > > > +   return integrity_inode_permission(file, NULL,
>> > > > > +                 mask & (MAY_READ | MAY_WRITE |
>> > > > > +                    MAY_EXEC));
>> > > >
>> > > > Please put your hook into inode_permission.  Note that in inode
>> > > > permission and lots of callers there is no path available so don't
>> pass
>> > > > it.  Please pass the full MAY_FOO mask for new interfaces and do
>> > > > filtering that won't break if new ones are introduced.
>> > >
>> > > We started out with the integrity_inode_permission() hook call in
>> > > inode_permission(), but because of the removal of the nameidata
>> > > parameter in the last merge, based on discussions
>> > > http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
>> > > the call to integrity_inode_permission() was moved up to the caller,
>> > > where either a file or path are available.  Any suggestions?
>> >
>> > Mimi, can you explain exactly (and concisely) what you are doing with
>> > the pathname?
>>
>> IMA maintains a list of hash values of system sensitive files loaded
>> into the run-time of the system and extends a PCR with the hash value.
>> In order to calculate this hash value, IMA requires access to either
>> the file or the path, which currently is not accessible in
>> inode_permission().
>
> So the usual question is, if I've done
>        ln -s /etc/shadow /tmp/shadow
> will IMA do the right thing if I'm opening /tmp/shadow?  Or will it only
> catch any writes I've done the next time someone (i.e. passwd) opens
> /etc/shadow?
>
> thanks,
> -serge

We really do need to get credentials patch in to common store all this
permission/secuirty data..  With a section for integrity related
entries.

Anti-Virus Passes and fails, signed running programs support and so on.

Lot of different things need ways of recording integrity status's.
Users also need to know if a application does not work is it TPM is it
Anti-virus is it lack of signature.

A common way of extracting what the blockage has to be the way
forward.  Since then this can be integrated into file managers and the
like.  Running like 12 different tools to find what blocked a program
is kinda wasteful.

 Sorting out this storage is kinda critical.  People could be running
a few different integrity systems side by side.

Peter Dolding

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-10 13:52     ` Mimi Zohar
  2008-08-11 17:02       ` Serge E. Hallyn
@ 2008-08-12 19:25       ` Christoph Hellwig
  1 sibling, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-12 19:25 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: Christoph Hellwig, linux-kernel, linux-security-module, Al Viro,
	Stephen Smalley, James Morris, Randy Dunlap, safford, serue,
	sailer, Mimi Zohar

On Sun, Aug 10, 2008 at 09:52:13AM -0400, Mimi Zohar wrote:
> We started out with the integrity_inode_permission() hook call in 
> inode_permission(), but because of the removal of the nameidata 
> parameter in the last merge, based on discussions
> http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
> the call to integrity_inode_permission() was moved up to the caller,
> where either a file or path are available.  Any suggestions?

vfs_permission and file_permission are just small wrappers around
inode_permission.  In hindsight they actualyl were a wrong idea and
will probably go away in the not so distant future.  Note that there
are various callers of inode_permission that don't have a vfsmount
anywhere near.


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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-11 17:02       ` Serge E. Hallyn
  2008-08-11 19:08         ` Mimi Zohar
@ 2008-08-12 19:27         ` Christoph Hellwig
  2008-08-12 21:19           ` Serge E. Hallyn
  1 sibling, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-12 19:27 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Mimi Zohar, Christoph Hellwig, linux-kernel,
	linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer, Mimi Zohar

On Mon, Aug 11, 2008 at 12:02:55PM -0500, Serge E. Hallyn wrote:
> > > Sorry, but I don't think we can bloat the inode even further for this.
> > 
> > The original version of IMA was LSM based, using i_security. Based
> > on discussions on the LSM mailing list, it was decided that the LSM hooks
> > were meant only for access control.  During the same time frame, there 
> > was a lot of work done in stacking LSM modules and i_security, but that
> > approach was dropped. It was suggested that we define a separate set of
> > hooks for integrity, which this patch set provides. Caching integrity 
> > results is an important aspect. Any suggestions in lieu of defining 
> > i_integrity?
> 
> The i_integrity is only bloating the inode if LIM is enabled.  Surely
> that beats having LIM define its own hash table and locking to track
> integrity labels on inodes?  Do you have another suggestion?
> 
> Or is the concern about having more #ifdefs in the struct inode
> definition?

No, the concern is over bloating the inode for a rather academic fringe
feature.  As this comes from IBM I'm pretty sure someone will pressure
the big distro to turn it on.  And inode growth is a concern for
fileserving or other inode heavy workload.  Mimi mentioned this is just
a cache of information, so consider using something like XFS's mru cache
which is used for something similar where the xfs_inode was kept small
despite a very niche feature needing a cache attached to the inode:

	fs/xfs/xfs_mru_cache.c

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-12  8:41             ` Peter Dolding
@ 2008-08-12 19:29               ` Christoph Hellwig
  2008-08-13 10:44                 ` Peter Dolding
  0 siblings, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-12 19:29 UTC (permalink / raw)
  To: Peter Dolding
  Cc: Serge E. Hallyn, Mimi Zohar, serue, Christoph Hellwig,
	James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, Al Viro, Mimi Zohar

On Tue, Aug 12, 2008 at 06:41:16PM +1000, Peter Dolding wrote:
> We really do need to get credentials patch in to common store all this
> permission/secuirty data..  With a section for integrity related
> entries.
> 
> Anti-Virus Passes and fails, signed running programs support and so on.
> 
> Lot of different things need ways of recording integrity status's.
> Users also need to know if a application does not work is it TPM is it
> Anti-virus is it lack of signature.

Peter, please read up what the credentials patches do, or how struct
cred/ucred is used in SVR4 and BSD for the last 20 years.  It is useful,
but it's not going to help with any of the strange thigns the AV or
Integrity people are doing.

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-11 21:13     ` Mimi Zohar
@ 2008-08-12 19:30       ` Christoph Hellwig
  2008-08-12 20:57         ` Kenneth Goldman
  0 siblings, 1 reply; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-12 19:30 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: Christoph Hellwig, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, serue, Al Viro, Debora Velarde, Mimi Zohar,
	Kenneth Goldman

On Mon, Aug 11, 2008 at 05:13:51PM -0400, Mimi Zohar wrote:
> 
> I assume the concern here is that between looking up the chip and actually 
> 
> using the chip, the TPM chip is disabled/deactivated.  Based on 
> discussions 
> with Kenneth Goldman, the TCG main specification part2: structures, 
> require
> that even if the TPM is disabled/deactivated, the command to extend the 
> PCR 
> will succeed, but the command to read the PCR will fail with an 
> appropriate 
> error code.

And what happens when the chip simply goes away due to a hotplug action?
Or not even the actual chip goes away but just the chip driver and you
now dereference freed memory?


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 19:30       ` Christoph Hellwig
@ 2008-08-12 20:57         ` Kenneth Goldman
  2008-08-12 21:36           ` Alan Cox
                             ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-12 20:57 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-kernel, linux-security-module, Mimi Zohar

Christoph Hellwig <hch@infradead.org> wrote on 08/12/2008 03:30:31 PM:

> On Mon, Aug 11, 2008 at 05:13:51PM -0400, Mimi Zohar wrote:
> >
> > I assume the concern here is that between looking up the chip and
actually
> >
> > using the chip, the TPM chip is disabled/deactivated.  Based on
> > discussions
> > with Kenneth Goldman, the TCG main specification part2: structures,
> > require
> > that even if the TPM is disabled/deactivated, the command to extend the

> > PCR
> > will succeed, but the command to read the PCR will fail with an
> > appropriate
> > error code.
>
> And what happens when the chip simply goes away due to a hotplug action?
> Or not even the actual chip goes away but just the chip driver and you
> now dereference freed memory?

Being a TCG/TPM person, I can only address the first question.  The
intent is that the TPM is soldered to the planar/motherboard (the TCG
uses the phrase "bound to the platform").  I can't imagine
any manufacturer designing a pluggable TPM.  It would subvert PCR
measurements and thus attestation, data sealing, etc.


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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-12 19:27         ` Christoph Hellwig
@ 2008-08-12 21:19           ` Serge E. Hallyn
  2008-08-13 17:03             ` Mimi Zohar
  0 siblings, 1 reply; 47+ messages in thread
From: Serge E. Hallyn @ 2008-08-12 21:19 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Mimi Zohar, linux-kernel, linux-security-module, Al Viro,
	Stephen Smalley, James Morris, Randy Dunlap, safford, serue,
	sailer, Mimi Zohar

Quoting Christoph Hellwig (hch@infradead.org):
> On Mon, Aug 11, 2008 at 12:02:55PM -0500, Serge E. Hallyn wrote:
> > > > Sorry, but I don't think we can bloat the inode even further for this.
> > > 
> > > The original version of IMA was LSM based, using i_security. Based
> > > on discussions on the LSM mailing list, it was decided that the LSM hooks
> > > were meant only for access control.  During the same time frame, there 
> > > was a lot of work done in stacking LSM modules and i_security, but that
> > > approach was dropped. It was suggested that we define a separate set of
> > > hooks for integrity, which this patch set provides. Caching integrity 
> > > results is an important aspect. Any suggestions in lieu of defining 
> > > i_integrity?
> > 
> > The i_integrity is only bloating the inode if LIM is enabled.  Surely
> > that beats having LIM define its own hash table and locking to track
> > integrity labels on inodes?  Do you have another suggestion?
> > 
> > Or is the concern about having more #ifdefs in the struct inode
> > definition?
> 
> No, the concern is over bloating the inode for a rather academic fringe
> feature.  As this comes from IBM I'm pretty sure someone will pressure
> the big distro to turn it on.

By default??  I should hope not...

Note that these are all not loadable modules.  So presumably either it's
in the kernel and enforcing, or it's not there.

> And inode growth is a concern for
> fileserving or other inode heavy workload.  Mimi mentioned this is just
> a cache of information, so consider using something like XFS's mru cache
> which is used for something similar where the xfs_inode was kept small
> despite a very niche feature needing a cache attached to the inode:
> 
> 	fs/xfs/xfs_mru_cache.c

ok, so basically as I said above

> > ... having LIM define its own hash table and locking to track
> > integrity labels on inodes?

:)

But then that is in fact the better way to go if there can be a lot
of inodes with i_integrity=NULL.  It looks like IMA always allocates
something, but if I understand the idea behind templates correctly,
that isn't necessarily always the case.

thanks,
-serge

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 20:57         ` Kenneth Goldman
@ 2008-08-12 21:36           ` Alan Cox
  2008-08-13 13:46             ` Kenneth Goldman
  2008-08-12 23:16           ` Greg KH
  2008-08-14 11:12           ` Pavel Machek
  2 siblings, 1 reply; 47+ messages in thread
From: Alan Cox @ 2008-08-12 21:36 UTC (permalink / raw)
  To: Kenneth Goldman
  Cc: Christoph Hellwig, linux-kernel, linux-security-module,
	Mimi Zohar

> Being a TCG/TPM person, I can only address the first question.  The
> intent is that the TPM is soldered to the planar/motherboard (the TCG
> uses the phrase "bound to the platform").  I can't imagine
> any manufacturer designing a pluggable TPM.  It would subvert PCR
> measurements and thus attestation, data sealing, etc.

So the security limit of your TPM is a soldering iron .. whoo. I'm not
sure this is actually the case however as the secret of interest is in
the TPM so even if I replaced the TPM the goodies already set up are in
the TPM I just unsoldered surely ?

Alan

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 20:57         ` Kenneth Goldman
  2008-08-12 21:36           ` Alan Cox
@ 2008-08-12 23:16           ` Greg KH
  2008-08-13 13:58             ` Kenneth Goldman
  2008-08-13 16:56             ` Mimi Zohar
  2008-08-14 11:12           ` Pavel Machek
  2 siblings, 2 replies; 47+ messages in thread
From: Greg KH @ 2008-08-12 23:16 UTC (permalink / raw)
  To: Kenneth Goldman
  Cc: Christoph Hellwig, linux-kernel, linux-security-module,
	Mimi Zohar

On Tue, Aug 12, 2008 at 04:57:31PM -0400, Kenneth Goldman wrote:
> Christoph Hellwig <hch@infradead.org> wrote on 08/12/2008 03:30:31 PM:
> 
> > On Mon, Aug 11, 2008 at 05:13:51PM -0400, Mimi Zohar wrote:
> > >
> > > I assume the concern here is that between looking up the chip and
> actually
> > >
> > > using the chip, the TPM chip is disabled/deactivated.  Based on
> > > discussions
> > > with Kenneth Goldman, the TCG main specification part2: structures,
> > > require
> > > that even if the TPM is disabled/deactivated, the command to extend the
> 
> > > PCR
> > > will succeed, but the command to read the PCR will fail with an
> > > appropriate
> > > error code.
> >
> > And what happens when the chip simply goes away due to a hotplug action?
> > Or not even the actual chip goes away but just the chip driver and you
> > now dereference freed memory?
> 
> Being a TCG/TPM person, I can only address the first question.  The
> intent is that the TPM is soldered to the planar/motherboard (the TCG
> uses the phrase "bound to the platform").  I can't imagine
> any manufacturer designing a pluggable TPM.  It would subvert PCR
> measurements and thus attestation, data sealing, etc.

Load up the fake-php hotplug pci driver and "soft" disconnect it from
the system :)

That was easy...

Note, just because you think your device is always going to be soldered
to the motherboard, doesn't mean it can't be disconnected at any point
in time with the kernel running.

Or the module could just be unloaded, that's also a very common thing to
have happen, right?

thanks,

greg k-h

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-12 19:29               ` Christoph Hellwig
@ 2008-08-13 10:44                 ` Peter Dolding
  2008-08-13 14:11                   ` David Howells
  0 siblings, 1 reply; 47+ messages in thread
From: Peter Dolding @ 2008-08-13 10:44 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Serge E. Hallyn, Mimi Zohar, serue, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, Al Viro, Mimi Zohar

On Wed, Aug 13, 2008 at 5:29 AM, Christoph Hellwig <hch@infradead.org> wrote:
> On Tue, Aug 12, 2008 at 06:41:16PM +1000, Peter Dolding wrote:
>> We really do need to get credentials patch in to common store all this
>> permission/secuirty data..  With a section for integrity related
>> entries.
>>
>> Anti-Virus Passes and fails, signed running programs support and so on.
>>
>> Lot of different things need ways of recording integrity status's.
>> Users also need to know if a application does not work is it TPM is it
>> Anti-virus is it lack of signature.
>
> Peter, please read up what the credentials patches do, or how struct
> cred/ucred is used in SVR4 and BSD for the last 20 years.  It is useful,
> but it's not going to help with any of the strange thigns the AV or
> Integrity people are doing.
>
The Issue I have.  By your answer you have not.   Credentials patch
for Linux allows more than the BSD one does.  Linux one is a complete
permission storage replacement.

http://linux.derkeiler.com/Mailing-Lists/Kernel/2008-08/msg02682.html

Note the file credentials one.  That is reused by FS Cache and it
creates fake inodes.  So worst case event LIM blocks a valid file
because its coming from cache.

"vfs_permission and file_permission are just small wrappers around
inode_permission."  No longer both go to inote_permission after the
credentials patch is in.   file_permission instead goes to credentials
struct connected to the inode.  Most calls to inode_permission end up
wrapped to the credentials struct.

Basically by the way Linux Credentials patch is being done.
inode_permission could completely cease to exist.    Completely
replaced by the credentials structure.

Each filesystem having its own cache is one reason why Linux
Credentials Patch is being brought into live.   So a single cache can
store all the need information of the OS and for the file system.
Even better operate on filesystems lacking all the need permission
structs using a userspace program to fill in some of the blanks.

LSM's in Credentials can there own protected data sets since all
alterations to Credentials by the user space deamon have to go past
LSM for approval or rejection.  Linux Credentials only need a extra
protected zone added to cover you LIM needs and AV needs to store
data.

In simple terms permissions stored in inodes is basically deprecated
by Linux's Credentials patch.

Sorting out the Credentials patch is kinda key.   Nothing you AV or
Integrity people is strange to the Linux Credentials patch.   Without
embracing requires more processing when pulling data from a common
cache that has already been AV or Integrity scanned and maintained in
that state.  Now its really designing the struct that should exist in
Credentials.

Peter Dolding

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-13 13:46             ` Kenneth Goldman
@ 2008-08-13 13:40               ` Alan Cox
  2008-08-13 14:45                 ` Christoph Hellwig
  2008-08-13 16:39                 ` Kenneth Goldman
  0 siblings, 2 replies; 47+ messages in thread
From: Alan Cox @ 2008-08-13 13:40 UTC (permalink / raw)
  To: Kenneth Goldman; +Cc: linux-kernel, linux-security-module

> "goodies", the TCG technology does not protect against hardware
> attacks such as replacing the TPM with a bogus device, replacing the
> CRTM hardware, flashing the CRTM using a JTAG cable, lifting a TPM pin>
> and asserting reset, using a JTAG cable to set breakpoints and alter
> memory, etc.
> 
> For this use case, the attack model is a remote, software attack.  The>
> user is not considered the attacker.

Surely if I can replace your TPM with alternative hardware then I can
also replace it with virtualised software traps.

[If there is a good document on this btw please just point me there
instead and I'll go read further]

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 21:36           ` Alan Cox
@ 2008-08-13 13:46             ` Kenneth Goldman
  2008-08-13 13:40               ` Alan Cox
  0 siblings, 1 reply; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-13 13:46 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, linux-security-module

Alan Cox <alan@lxorguk.ukuu.org.uk> wrote on 08/12/2008 05:36:36 PM:

> > Being a TCG/TPM person, I can only address the first question.  The
> > intent is that the TPM is soldered to the planar/motherboard (the TCG
> > uses the phrase "bound to the platform").  I can't imagine
> > any manufacturer designing a pluggable TPM.  It would subvert PCR
> > measurements and thus attestation, data sealing, etc.
>
> So the security limit of your TPM is a soldering iron .. whoo. I'm not
> sure this is actually the case however as the secret of interest is in
> the TPM so even if I replaced the TPM the goodies already set up are in
> the TPM I just unsoldered surely ?

I suppose it depends on the precise interpretation of your technical
term "goodies".  :-)

One of the two primary uses of the TCG technology is protection
against an attack on the software.  The TCG uses the terms
attestation, integrity, platform measurements, etc.  For this class of>
"goodies", the TCG technology does not protect against hardware
attacks such as replacing the TPM with a bogus device, replacing the
CRTM hardware, flashing the CRTM using a JTAG cable, lifting a TPM pin>
and asserting reset, using a JTAG cable to set breakpoints and alter
memory, etc.

For this use case, the attack model is a remote, software attack.  The>
user is not considered the attacker.

(In the other primary use case, the user is the attacker, but it's an
entirely different discussion.)

(It's also important to note that the TPM itself does not completely
secure the platform.  There's an entire system design around it, which>
it why I try to say "TCG technology" rather than TPM.)


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 23:16           ` Greg KH
@ 2008-08-13 13:58             ` Kenneth Goldman
  2008-08-13 16:56             ` Mimi Zohar
  1 sibling, 0 replies; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-13 13:58 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, linux-security-module

Greg KH <greg@kroah.com> wrote on 08/12/2008 07:16:02 PM:

> On Tue, Aug 12, 2008 at 04:57:31PM -0400, Kenneth Goldman wrote:
> > Christoph Hellwig <hch@infradead.org> wrote on 08/12/2008 03:30:31 PM:
> >
> > > And what happens when the chip simply goes away due to a hotplug
action?
> > > Or not even the actual chip goes away but just the chip driver and
you
> > > now dereference freed memory?
> >
> > Being a TCG/TPM person, I can only address the first question.  The
> > intent is that the TPM is soldered to the planar/motherboard (the TCG
> > uses the phrase "bound to the platform").  I can't imagine
> > any manufacturer designing a pluggable TPM.  It would subvert PCR
> > measurements and thus attestation, data sealing, etc.
>
> Load up the fake-php hotplug pci driver and "soft" disconnect it from
> the system :)
>
> That was easy...
>
> Note, just because you think your device is always going to be soldered
> to the motherboard, doesn't mean it can't be disconnected at any point
> in time with the kernel running.
>
> Or the module could just be unloaded, that's also a very common thing to
> have happen, right?

As I said, I'm a TCG/TPM person, so I can't address "the module could just
be unloaded" or "hotplug pci driver".  I'll leave that issue to the
Linux driver experts.

I was using the common meaning of hotplug, removing and replacing a
hardware component while power is on.  By that common definition, the
TPM would not be a hotpluggable component.

(As an aside, the TPM is commonly connected to the LPC bus on
the planar, not the PCI bus.)


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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-13 10:44                 ` Peter Dolding
@ 2008-08-13 14:11                   ` David Howells
  2008-08-13 22:57                     ` Peter Dolding
  0 siblings, 1 reply; 47+ messages in thread
From: David Howells @ 2008-08-13 14:11 UTC (permalink / raw)
  To: Peter Dolding
  Cc: dhowells, Christoph Hellwig, Serge E. Hallyn, Mimi Zohar, serue,
	James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, Al Viro, Mimi Zohar

Peter Dolding <oiaohm@gmail.com> wrote:

> Credentials patch for Linux allows more than the BSD one does.  Linux one is
> a complete permission storage replacement.

No, it isn't.  It replaces the permission storage facility of a process but
does not change the way in which an inode caches its credentials in RAM.

> http://linux.derkeiler.com/Mailing-Lists/Kernel/2008-08/msg02682.html
> 
> Note the file credentials one.

I said "Open file credentials".  I was referring to struct file which
designates an open file handle, not the file/inode itself.  What this means is
that the open file handle takes a reference to the subjective security context
of the process that opened it, at the time it opened it, so that accesses to
that file are (with exceptions) done with those credentials, no matter who is
actually using the handle.

For disk filesystems, for the most part, this makes no difference: an open file
is usable by anyone who has the handle.  However, for network filesystems,
where each request is marked with the details of who the request should be
accounted to and the server decides, it does matter.

> That is reused by FS Cache and it creates fake inodes.

FS-Cache+CacheFiles doesn't create fake inodes at all.  It creates real inodes
on disk in the cache.  The reason for these patches is that CacheFiles needs to
use its own subjective security context when creating or accessing these
inodes, rather than the subjective context of whoever invoked AFS or NFS, and
thus caused CacheFiles to touch the cache.

> "vfs_permission and file_permission are just small wrappers around
> inode_permission."  No longer both go to inote_permission after the
> credentials patch is in.   file_permission instead goes to credentials
> struct connected to the inode.  Most calls to inode_permission end up
> wrapped to the credentials struct.

I don't understand what you're talking about.  Looking in fs/namei.c, I see:

	int vfs_permission(struct nameidata *nd, int mask)
	{
		return inode_permission(nd->path.dentry->d_inode, mask);
	}

And:

	int file_permission(struct file *file, int mask)
	{
		return inode_permission(file->f_path.dentry->d_inode, mask);
	}

That looks like they still both go to inode_permission().

> Basically by the way Linux Credentials patch is being done.
> inode_permission could completely cease to exist.    Completely
> replaced by the credentials structure.

Erm...  Why?  inode_permission() is a function, the creds struct is a data
type.

> Each filesystem having its own cache is one reason why Linux Credentials
> Patch is being brought into live.

Not as far as I know.  The credentials belonging to the filesystem and the
inodes in the filesystem belong to the filesystem and are not held in cred
structs.  Using cred structs for inodes would waste memory as a task's
credentials have a lot of bits an inode's don't.

> So a single cache can store all the need information of the OS and for the
> file system.  Even better operate on filesystems lacking all the need
> permission structs using a userspace program to fill in some of the blanks.
>
> LSM's in Credentials can there own protected data sets since all
> alterations to Credentials by the user space deamon have to go past
> LSM for approval or rejection.  Linux Credentials only need a extra
> protected zone added to cover you LIM needs and AV needs to store
> data.

Are you suggesting the offloading of security data caching to userspace?

> In simple terms permissions stored in inodes is basically deprecated
> by Linux's Credentials patch.

In simple terms, no they aren't.

> Sorting out the Credentials patch is kinda key.   Nothing you AV or
> Integrity people is strange to the Linux Credentials patch.   Without
> embracing requires more processing when pulling data from a common
> cache that has already been AV or Integrity scanned and maintained in
> that state.  Now its really designing the struct that should exist in
> Credentials.

>From my quick glance over the integrity patches, I'd say that the cred struct
is entirely the wrong place to store this data.  It's nothing to do with a
task's subjective state, except, perhaps, in setting it up.  It appears to be
per-inode state.

David

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-13 13:40               ` Alan Cox
@ 2008-08-13 14:45                 ` Christoph Hellwig
  2008-08-13 16:39                 ` Kenneth Goldman
  1 sibling, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2008-08-13 14:45 UTC (permalink / raw)
  To: Alan Cox; +Cc: Kenneth Goldman, linux-kernel, linux-security-module

On Wed, Aug 13, 2008 at 02:40:40PM +0100, Alan Cox wrote:
> > "goodies", the TCG technology does not protect against hardware
> > attacks such as replacing the TPM with a bogus device, replacing the
> > CRTM hardware, flashing the CRTM using a JTAG cable, lifting a TPM pin>
> > and asserting reset, using a JTAG cable to set breakpoints and alter
> > memory, etc.
> > 
> > For this use case, the attack model is a remote, software attack.  The>
> > user is not considered the attacker.
> 
> Surely if I can replace your TPM with alternative hardware then I can
> also replace it with virtualised software traps.

Yes, which in fact is what most people working on TPM support use
because the real hardware is just too slow :)

> [If there is a good document on this btw please just point me there
> instead and I'll go read further]

I recommend this one:
http://www.few.vu.nl/~srijith/publications/confs/sws07-final.pdf  :)


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-13 13:40               ` Alan Cox
  2008-08-13 14:45                 ` Christoph Hellwig
@ 2008-08-13 16:39                 ` Kenneth Goldman
  1 sibling, 0 replies; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-13 16:39 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, linux-security-module

Alan Cox <alan@lxorguk.ukuu.org.uk> wrote on 08/13/2008 09:40:40 AM:

> > "goodies", the TCG technology does not protect against hardware
> > attacks such as replacing the TPM with a bogus device, replacing the
> > CRTM hardware, flashing the CRTM using a JTAG cable, lifting a TPM pin>
> > and asserting reset, using a JTAG cable to set breakpoints and alter
> > memory, etc.
> >
> > For this use case, the attack model is a remote, software attack.  The>
> > user is not considered the attacker.
>
> Surely if I can replace your TPM with alternative hardware then I can
> also replace it with virtualised software traps.

Replacing with alternative hardware is outside the attack model.  For this
use case, the TCG assumes the user will not be attacking himself.

Replacing with software is a valid remote attack.  It will be detected
through the TCG platform measurement process.  The local defense is
"sealing" data to trusted measurements.  The remote defense is
"attestation" or "quote", getting signed measurements and deciding
whether to trust them.

> [If there is a good document on this btw please just point me there
> instead and I'll go read further]

The TPM main specification (design principles) discusses measurements,>
reporting, attestation, and so on.

The "TCG PC Client Specific Implementation Specification For Conventional
BIOS" is specific to the PC platform (there are specifications for mobile
devices, printers, storage, etc.) but section 1.2 has a good discussion
of the concepts.

https://www.trustedcomputinggroup.org/home

(Feel free to email me privately if this is becoming off topic for the
mailing list.)


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 23:16           ` Greg KH
  2008-08-13 13:58             ` Kenneth Goldman
@ 2008-08-13 16:56             ` Mimi Zohar
  1 sibling, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-13 16:56 UTC (permalink / raw)
  To: Greg KH
  Cc: Christoph Hellwig, Kenneth Goldman, linux-kernel,
	linux-security-module, linux-security-module-owner

linux-security-module-owner@vger.kernel.org wrote on 08/12/2008 07:16:02 
PM:

> On Tue, Aug 12, 2008 at 04:57:31PM -0400, Kenneth Goldman wrote:
> > Christoph Hellwig <hch@infradead.org> wrote on 08/12/2008 03:30:31 PM:
> > 
> > > On Mon, Aug 11, 2008 at 05:13:51PM -0400, Mimi Zohar wrote:
> > > >
> > > > I assume the concern here is that between looking up the chip and
> > actually
> > > >
> > > > using the chip, the TPM chip is disabled/deactivated.  Based on
> > > > discussions
> > > > with Kenneth Goldman, the TCG main specification part2: 
structures,
> > > > require
> > > > that even if the TPM is disabled/deactivated, the command to 
extend the
> > 
> > > > PCR
> > > > will succeed, but the command to read the PCR will fail with an
> > > > appropriate
> > > > error code.
> > >
> > > And what happens when the chip simply goes away due to a hotplug 
action?
> > > Or not even the actual chip goes away but just the chip driver and 
you
> > > now dereference freed memory?
> > 
> > Being a TCG/TPM person, I can only address the first question.  The
> > intent is that the TPM is soldered to the planar/motherboard (the TCG
> > uses the phrase "bound to the platform").  I can't imagine
> > any manufacturer designing a pluggable TPM.  It would subvert PCR
> > measurements and thus attestation, data sealing, etc.
> 
> Load up the fake-php hotplug pci driver and "soft" disconnect it from
> the system :)
> 
> That was easy...
> 
> Note, just because you think your device is always going to be soldered
> to the motherboard, doesn't mean it can't be disconnected at any point
> in time with the kernel running.
>
> Or the module could just be unloaded, that's also a very common thing to
> have happen, right?

This problem only affects the TPM internal kernel interface, if the TPM 
driver is not built-in. For IMA, this is not an issue as the TPM driver 
must be built-in in order to start collecting measurements as soon as 
possible, which is at late_initcall().  I will resolve this problem for 
the general internal kernel interface usage case.

Thanks!

Mimi

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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-12 21:19           ` Serge E. Hallyn
@ 2008-08-13 17:03             ` Mimi Zohar
  0 siblings, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-13 17:03 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Christoph Hellwig, Mimi Zohar, linux-kernel,
	linux-security-module, Al Viro, Stephen Smalley, James Morris,
	Randy Dunlap, safford, serue, sailer

On Tue, 2008-08-12 at 16:19 -0500, Serge E. Hallyn wrote: 
> Quoting Christoph Hellwig (hch@infradead.org):
> > On Mon, Aug 11, 2008 at 12:02:55PM -0500, Serge E. Hallyn wrote:
> > > > > Sorry, but I don't think we can bloat the inode even further for this.
> > > > 
> > > > The original version of IMA was LSM based, using i_security. Based
> > > > on discussions on the LSM mailing list, it was decided that the LSM hooks
> > > > were meant only for access control.  During the same time frame, there 
> > > > was a lot of work done in stacking LSM modules and i_security, but that
> > > > approach was dropped. It was suggested that we define a separate set of
> > > > hooks for integrity, which this patch set provides. Caching integrity 
> > > > results is an important aspect. Any suggestions in lieu of defining 
> > > > i_integrity?
> > > 
> > > The i_integrity is only bloating the inode if LIM is enabled.  Surely
> > > that beats having LIM define its own hash table and locking to track
> > > integrity labels on inodes?  Do you have another suggestion?
> > > 
> > > Or is the concern about having more #ifdefs in the struct inode
> > > definition?
> > 
> > No, the concern is over bloating the inode for a rather academic fringe
> > feature.  As this comes from IBM I'm pretty sure someone will pressure
> > the big distro to turn it on.
> 
> By default??  I should hope not...
> 
> Note that these are all not loadable modules.  So presumably either it's
> in the kernel and enforcing, or it's not there.
> 
> > And inode growth is a concern for
> > fileserving or other inode heavy workload.  Mimi mentioned this is just
> > a cache of information, so consider using something like XFS's mru cache
> > which is used for something similar where the xfs_inode was kept small
> > despite a very niche feature needing a cache attached to the inode:
> > 
> > 	fs/xfs/xfs_mru_cache.c
> 
> ok, so basically as I said above
> 
> > > ... having LIM define its own hash table and locking to track
> > > integrity labels on inodes?
> 
> :)
> 
> But then that is in fact the better way to go if there can be a lot
> of inodes with i_integrity=NULL.  It looks like IMA always allocates
> something, but if I understand the idea behind templates correctly,
> that isn't necessarily always the case.
> 
> thanks,
> -serge

IMA has a two stage initialization, one at security_initcall() and 
another at late_initcall(), when the tpm is available, to make sure 
that all inode's i_integrity are allocated.  

Multiple templates can register themselves with LIM, but only one
integrity provider, such as IMA, can register itself at a time. So
hypothetically, other integrity providers could be implemented 
without a need for i_integrity.

Mimi


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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-11 19:56           ` Serge E. Hallyn
  2008-08-12  8:41             ` Peter Dolding
@ 2008-08-13 17:03             ` Mimi Zohar
  1 sibling, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-08-13 17:03 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: Mimi Zohar, serue, Christoph Hellwig, James Morris, linux-kernel,
	linux-security-module, Randy Dunlap, safford, sailer,
	Stephen Smalley, Al Viro

On Mon, 2008-08-11 at 14:56 -0500, Serge E. Hallyn wrote: 
> Quoting Mimi Zohar (zohar@us.ibm.com):
> > serue@linux.vnet.ibm.com wrote on 08/11/2008 01:02:55 PM:
> > 
> > > Quoting Mimi Zohar (zohar@us.ibm.com):
> > > > Christoph Hellwig <hch@infradead.org> wrote on 08/09/2008 02:53:40 PM:
> > > > > >  int vfs_permission(struct nameidata *nd, int mask)
> > > > > >  {
> > > > > > -   return inode_permission(nd->path.dentry->d_inode, mask);
> > > > > > +   int retval;
> > > > > > +
> > > > > > +   retval = inode_permission(nd->path.dentry->d_inode, mask);
> > > > > > +   if (retval)
> > > > > > +      return retval;
> > > > > > +   return integrity_inode_permission(NULL, &nd->path,
> > > > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > > > +                    MAY_EXEC));
> > > > > >  }
> > > > > > 
> > > > > >  /**
> > > > > > @@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd,
> > > > > >   */
> > > > > >  int file_permission(struct file *file, int mask)
> > > > > >  {
> > > > > > -   return inode_permission(file->f_path.dentry->d_inode, mask);
> > > > > > +   int retval;
> > > > > > +
> > > > > > +   retval = inode_permission(file->f_path.dentry->d_inode, mask);
> > > > > > +   if (retval)
> > > > > > +      return retval;
> > > > > > +   return integrity_inode_permission(file, NULL,
> > > > > > +                 mask & (MAY_READ | MAY_WRITE |
> > > > > > +                    MAY_EXEC));
> > > > > 
> > > > > Please put your hook into inode_permission.  Note that in inode
> > > > > permission and lots of callers there is no path available so don't 
> > pass
> > > > > it.  Please pass the full MAY_FOO mask for new interfaces and do
> > > > > filtering that won't break if new ones are introduced.
> > > > 
> > > > We started out with the integrity_inode_permission() hook call in 
> > > > inode_permission(), but because of the removal of the nameidata 
> > > > parameter in the last merge, based on discussions
> > > > http://marc.info/?l=linux-security-module&m=121797845308246&w=2,
> > > > the call to integrity_inode_permission() was moved up to the caller,
> > > > where either a file or path are available.  Any suggestions?
> > > 
> > > Mimi, can you explain exactly (and concisely) what you are doing with
> > > the pathname?
> > 
> > IMA maintains a list of hash values of system sensitive files loaded 
> > into the run-time of the system and extends a PCR with the hash value. 
> > In order to calculate this hash value, IMA requires access to either
> > the file or the path, which currently is not accessible in 
> > inode_permission().
> 
> So the usual question is, if I've done	
> 	ln -s /etc/shadow /tmp/shadow
> will IMA do the right thing if I'm opening /tmp/shadow?  Or will it only
> catch any writes I've done the next time someone (i.e. passwd) opens
> /etc/shadow?

It will measure the right thing, as the measurement is based on the dentry
contained within the file/path structures, not names.  File names in IMA 
are only used as a hint in the measurement hash list.

Mimi


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

* Re: [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-08-13 14:11                   ` David Howells
@ 2008-08-13 22:57                     ` Peter Dolding
  0 siblings, 0 replies; 47+ messages in thread
From: Peter Dolding @ 2008-08-13 22:57 UTC (permalink / raw)
  To: David Howells
  Cc: Christoph Hellwig, Serge E. Hallyn, Mimi Zohar, serue,
	James Morris, linux-kernel, linux-security-module, Randy Dunlap,
	safford, sailer, Stephen Smalley, Al Viro, Mimi Zohar

On Thu, Aug 14, 2008 at 12:11 AM, David Howells <dhowells@redhat.com> wrote:
> Peter Dolding <oiaohm@gmail.com> wrote:
>
>> Credentials patch for Linux allows more than the BSD one does.  Linux one is
>> a complete permission storage replacement.
>
> No, it isn't.  It replaces the permission storage facility of a process but
> does not change the way in which an inode caches its credentials in RAM.
>
>> http://linux.derkeiler.com/Mailing-Lists/Kernel/2008-08/msg02682.html
>>
>> Note the file credentials one.
>
> I said "Open file credentials".  I was referring to struct file which
> designates an open file handle, not the file/inode itself.  What this means is
> that the open file handle takes a reference to the subjective security context
> of the process that opened it, at the time it opened it, so that accesses to
> that file are (with exceptions) done with those credentials, no matter who is
> actually using the handle.
>
> For disk filesystems, for the most part, this makes no difference: an open file
> is usable by anyone who has the handle.  However, for network filesystems,
> where each request is marked with the details of who the request should be
> accounted to and the server decides, it does matter.
>
>> That is reused by FS Cache and it creates fake inodes.
>
> FS-Cache+CacheFiles doesn't create fake inodes at all.  It creates real inodes
> on disk in the cache.  The reason for these patches is that CacheFiles needs to
> use its own subjective security context when creating or accessing these
> inodes, rather than the subjective context of whoever invoked AFS or NFS, and
> thus caused CacheFiles to touch the cache.
>
Source of Inodes is different.   Old style attack aganst AV's has been
to get them to approve something then swap the contents while its
still approved.  Simplest is cache attacking.   We need to single up
the cache with secuirty around it.

Other cache that has been targeted is the swapfile.  Since its another
cache.   Building solid intergeity its key to get control of the
caches.

>> "vfs_permission and file_permission are just small wrappers around
>> inode_permission."  No longer both go to inote_permission after the
>> credentials patch is in.   file_permission instead goes to credentials
>> struct connected to the inode.  Most calls to inode_permission end up
>> wrapped to the credentials struct.
>
> I don't understand what you're talking about.  Looking in fs/namei.c, I see:
>
>        int vfs_permission(struct nameidata *nd, int mask)
>        {
>                return inode_permission(nd->path.dentry->d_inode, mask);
>        }
>
> And:
>
>        int file_permission(struct file *file, int mask)
>        {
>                return inode_permission(file->f_path.dentry->d_inode, mask);
>        }
>
> That looks like they still both go to inode_permission().

Hmm I had redirect file_permission in my own working tree.  Experiment
in reduced storage in the inode and credentionals  systems.

If you look at inode in operation you might as well call the file
permissions on a per file base.  All found so far are the pointer to
the same struct if its exactly the same file.

Its a point of duplication of storage.  Credentials and inode storing it.

Ie file permissions only stored once.
>> Basically by the way Linux Credentials patch is being done.
>> inode_permission could completely cease to exist.    Completely
>> replaced by the credentials structure.
>
> Erm...  Why?  inode_permission() is a function, the creds struct is a data
> type.
>
>> Each filesystem having its own cache is one reason why Linux Credentials
>> Patch is being brought into live.
>
> Not as far as I know.  The credentials belonging to the filesystem and the
> inodes in the filesystem belong to the filesystem and are not held in cred
> structs.  Using cred structs for inodes would waste memory as a task's
> credentials have a lot of bits an inode's don't.
>
>> So a single cache can store all the need information of the OS and for the
>> file system.  Even better operate on filesystems lacking all the need
>> permission structs using a userspace program to fill in some of the blanks.
>>
>> LSM's in Credentials can there own protected data sets since all
>> alterations to Credentials by the user space deamon have to go past
>> LSM for approval or rejection.  Linux Credentials only need a extra
>> protected zone added to cover you LIM needs and AV needs to store
>> data.
>
> Are you suggesting the offloading of security data caching to userspace?

Not for caching mainly.  For some operations intergretiy might be
chosen to be done in user space like if file is signed or not.   Like
checking just using userspace drivers.   Remember you can already
insert userspace drivers in theory for testing of a TPM setup running
from userspace in a small section of the OS could be useful to make
sure everything is right before making active.

Strict interface allowing sections of the security system to operate
in user space and kernel space.  For allowing existence of a combined
defence.

AV program may be approved to set X integrity data in credentials.

Signature checking program might set a flag to say that a application
should never run as root or that its a particular class of
application.   Triggering the LSM to auto reduce applications that
programs system access to match its settings.   For this to be
possible we need secuirty that only the Signature checking program can
set the signature flags.  Then the LSM can trust and repond to them.
 This is bring ipset's style for firewalls http://ipset.netfilter.org/
 to the main secuirty system.

Having both kernel and usermode existing in secuirty has the same
advantage as allowing user mode drivers.  The userspace to be
changeable with threats and independent to kernel.

Most creative expands I am looking into.

Giving Linux equal to layor 7 file wall filtering on the filesystem
level.  file id magics run on file when before the file is opened by
the application that information stored in credentials.   If a program
is no meant to open that file type it can be gets blocked.  When
running anti-virus and many filemangers side by side they don't need
to run magics repetitively.

Final one is a new form of file interlink.  Bit like streams in NTFS.
So thumbnails and the like of images used by filemanagers are
connected to there related file.   So when deleting the file a thumb
nail was created from the thumbnail gets removed.   Hopefully allowing
applications to save on down scaling as well.

Yes I am really messing around in the current internal structs.  To
hopefully provide a framework to archive the max secuirty creatable.
As well as reducing duplication.  So price of doing MAX should be
quite min.
>
>> In simple terms permissions stored in inodes is basically deprecated
>> by Linux's Credentials patch.
>
> In simple terms, no they aren't.

>From the way I am doing it.  Storing shared permissions between files
it is deprecated for the inodes stuct.  Since I altered the code to
move that into credentials alone.   I was thinking too much in my
working tree.
>
>> Sorting out the Credentials patch is kinda key.   Nothing you AV or
>> Integrity people is strange to the Linux Credentials patch.   Without
>> embracing requires more processing when pulling data from a common
>> cache that has already been AV or Integrity scanned and maintained in
>> that state.  Now its really designing the struct that should exist in
>> Credentials.
>
> From my quick glance over the integrity patches, I'd say that the cred struct
> is entirely the wrong place to store this data.  It's nothing to do with a
> task's subjective state, except, perhaps, in setting it up.  It appears to be
> per-inode state.
>

Its the  in operation of the LIM.   Same as AV.  Complete files will
be scanned.  Passed or failed or marked unknown.   Currently we have
nice duplication of lots of things.  Its been the alteration in my
working tree that has given me  major different look at how to do
this.    I am trying to get to a location where there is no
duplication of permission storage or caching.   Simpler to audit
system access 1 struct know operational and real storage state.

Peter Dolding

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-12 20:57         ` Kenneth Goldman
  2008-08-12 21:36           ` Alan Cox
  2008-08-12 23:16           ` Greg KH
@ 2008-08-14 11:12           ` Pavel Machek
  2008-08-15 10:37             ` Peter Dolding
  2008-08-18 15:01             ` Kenneth Goldman
  2 siblings, 2 replies; 47+ messages in thread
From: Pavel Machek @ 2008-08-14 11:12 UTC (permalink / raw)
  To: Kenneth Goldman
  Cc: Christoph Hellwig, linux-kernel, linux-security-module,
	Mimi Zohar

Hi!

> > And what happens when the chip simply goes away due to a hotplug action?
> > Or not even the actual chip goes away but just the chip driver and you
> > now dereference freed memory?
> 
> Being a TCG/TPM person, I can only address the first question.  The
> intent is that the TPM is soldered to the planar/motherboard (the TCG
> uses the phrase "bound to the platform").  I can't imagine
> any manufacturer designing a pluggable TPM.  It would subvert PCR

Only 2 TPMs I've seen were on pluggable modules... which was fortunate
because they slowed down boot by 5+ minutes, and broke it completely
in other cases. Nickname 'kurvitko' (aka useless trash that breaks
stuff). They are currently lying under my table, disconnected.

(OTOH they were not on PCI, but on some low-count pin header).
							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-14 11:12           ` Pavel Machek
@ 2008-08-15 10:37             ` Peter Dolding
  2008-08-15 18:50               ` Kenneth Goldman
  2008-08-18 15:01             ` Kenneth Goldman
  1 sibling, 1 reply; 47+ messages in thread
From: Peter Dolding @ 2008-08-15 10:37 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Kenneth Goldman, Christoph Hellwig, linux-kernel,
	linux-security-module, Mimi Zohar

On Thu, Aug 14, 2008 at 9:12 PM, Pavel Machek <pavel@suse.cz> wrote:
> Hi!
>
>> > And what happens when the chip simply goes away due to a hotplug action?
>> > Or not even the actual chip goes away but just the chip driver and you
>> > now dereference freed memory?
>>
>> Being a TCG/TPM person, I can only address the first question.  The
>> intent is that the TPM is soldered to the planar/motherboard (the TCG
>> uses the phrase "bound to the platform").  I can't imagine
>> any manufacturer designing a pluggable TPM.  It would subvert PCR
>
> Only 2 TPMs I've seen were on pluggable modules... which was fortunate
> because they slowed down boot by 5+ minutes, and broke it completely
> in other cases. Nickname 'kurvitko' (aka useless trash that breaks
> stuff). They are currently lying under my table, disconnected.
>
> (OTOH they were not on PCI, but on some low-count pin header).
>                                                        Pavel
Remember even soldered on stuff can fail.   How linux handles the
death of the TPM module needs to be covered.

Peter Dolding

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-15 10:37             ` Peter Dolding
@ 2008-08-15 18:50               ` Kenneth Goldman
  2008-08-15 19:22                 ` Valdis.Kletnieks
  2008-08-15 21:17                 ` Alan Cox
  0 siblings, 2 replies; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-15 18:50 UTC (permalink / raw)
  To: Peter Dolding; +Cc: linux-kernel, linux-security-module

"Peter Dolding" <oiaohm@gmail.com> wrote on 08/15/2008 06:37:27 AM:

> Remember even soldered on stuff can fail.   How linux handles the
> death of the TPM module needs to be covered.

Is fault tolerance a requirement just for the TPM, or is it a general>
Linux requirement?  Has it always been there, or is it new?

For example, does kernel software have to gracefully handle
failures in the disk controller, processor, memory controller, BIOS
flash memory, etc?

I'd think it would be quite hard to code around motherboard
failures in a commodity platform not designed for fault tolerance.


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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-15 18:50               ` Kenneth Goldman
@ 2008-08-15 19:22                 ` Valdis.Kletnieks
  2008-08-15 21:17                 ` Alan Cox
  1 sibling, 0 replies; 47+ messages in thread
From: Valdis.Kletnieks @ 2008-08-15 19:22 UTC (permalink / raw)
  To: Kenneth Goldman; +Cc: Peter Dolding, linux-kernel, linux-security-module

[-- Attachment #1: Type: text/plain, Size: 1316 bytes --]

On Fri, 15 Aug 2008 14:50:01 EDT, Kenneth Goldman said:
> "Peter Dolding" <oiaohm@gmail.com> wrote on 08/15/2008 06:37:27 AM:
> 
> > Remember even soldered on stuff can fail.   How linux handles the
> > death of the TPM module needs to be covered.
> 
> Is fault tolerance a requirement just for the TPM, or is it a general>
> Linux requirement?  Has it always been there, or is it new?
> 
> For example, does kernel software have to gracefully handle
> failures in the disk controller, processor, memory controller, BIOS
> flash memory, etc?

Well, on a dual/quad core/socket/whatever system, a failing processor
can be downed and the system keep going.  On a NUMA box, you can yank a
node with a bad memory controller after you take it down.  Similarly for
a disk controller if you have more than one, and the failed one isn't
critical for system operation.

And the TPM chip is more like a USB controller, in that there's a *high*
degree of probability that the system will still be able to run even if it
fails or goes insane (consider that on my laptop, the TPM driver was broken
for a while, and I was still ableto work).  So you need to write code to
do things like detect TPM downage or insanity, decide what to do on the
kernel level, what to reflect up to any security modules running in
userspace, etc....

[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-15 18:50               ` Kenneth Goldman
  2008-08-15 19:22                 ` Valdis.Kletnieks
@ 2008-08-15 21:17                 ` Alan Cox
  1 sibling, 0 replies; 47+ messages in thread
From: Alan Cox @ 2008-08-15 21:17 UTC (permalink / raw)
  To: Kenneth Goldman; +Cc: Peter Dolding, linux-kernel, linux-security-module

On Fri, 15 Aug 2008 14:50:01 -0400
Kenneth Goldman <kgoldman@us.ibm.com> wrote:

> "Peter Dolding" <oiaohm@gmail.com> wrote on 08/15/2008 06:37:27 AM:
> 
> > Remember even soldered on stuff can fail.   How linux handles the
> > death of the TPM module needs to be covered.
> 
> Is fault tolerance a requirement just for the TPM, or is it a general>
> Linux requirement?  Has it always been there, or is it new?

We try very very hard to not crash on failure.

> For example, does kernel software have to gracefully handle
> failures in the disk controller, processor, memory controller, BIOS
> flash memory, etc?

Our disk layer will retry, reset, change cable speeds and if that fails
and you are running raid with multipaths or sufficient mirrors continue.
We capture processor exceptions and when possible log and continue
although most CPU failures report with the context corrupt. We log and
the EDAC layer handles as much as it possible can for memory errors
(actually we could be a bit more selective here and there are proposals
to go  further)

> I'd think it would be quite hard to code around motherboard
> failures in a commodity platform not designed for fault tolerance.

The Linux userbase ranges from fault tolerant systems like Stratus to
dodgy cheapo boards from iffy cheap and cheerful computer merchants so it
makes sense to try and be robust.

In your TPM case being robust against the TPM ceasing to respond
certainly is worthwhile so that at least you return an error on failure
rather than the box dying. You may well not be able to get the chip back
in order without a hardware change/reboot.

Alan

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

* Re: [PATCH 1/4] integrity: TPM internel kernel interface
  2008-08-14 11:12           ` Pavel Machek
  2008-08-15 10:37             ` Peter Dolding
@ 2008-08-18 15:01             ` Kenneth Goldman
  1 sibling, 0 replies; 47+ messages in thread
From: Kenneth Goldman @ 2008-08-18 15:01 UTC (permalink / raw)
  To: Pavel Machek; +Cc: linux-kernel, linux-security-module

Pavel Machek <pavel@suse.cz> wrote on 08/14/2008 07:12:10 AM:

> Only 2 TPMs I've seen were on pluggable modules... which was fortunate
> because they slowed down boot by 5+ minutes, and broke it completely
> in other cases. Nickname 'kurvitko' (aka useless trash that breaks
> stuff). They are currently lying under my table, disconnected.
>
> (OTOH they were not on PCI, but on some low-count pin header).

1 - The pluggable modules use a standard LPC bus header.  In my>
experience, all the TPM vendors supply them in low quantities for
evaluation and test, but no one expects them to be used in
production because of the security issues.

2 - I'd be interested to know whether the slowdown was in
the BIOS, in the OS boot, or on bringup of an application?
Was this Linux or some other OS?

Both the TCG and the platform vendors are very sensitive to
the BIOS part of the boot time.  For example, the TPM self test
is broken into a fast part for features that are required
before boot and a slower part that can be done later. There
are recommendations to break up hashing to remove the TPM
from the critical path.

Even then, the slowest TPM operation is keypair creation,
on the order of 1-5 seconds, which should not be required
during boot.  I wonder if the problem was actually a code
bug or unsupported operation causing timeouts?

It would be great if you could debug a bit and report your
findings to us.


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

* [PATCH 3/4] integrity: Linux Integrity Module(LIM)
  2008-10-07 18:00 [PATCH 0/4] integrity Mimi Zohar
@ 2008-10-07 18:00 ` Mimi Zohar
  0 siblings, 0 replies; 47+ messages in thread
From: Mimi Zohar @ 2008-10-07 18:00 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mimi Zohar, Andrew Morton, James Morris, Christoph Hellwig,
	Al Viro, David Safford, Serge Hallyn, Mimi Zohar

Concern was raised on the lkml mailing list, about adding i_integrity
to the inode structure.  This patch adds a comment clarifying that
i_integrity is only included in the inode if INTEGRITY is configured.

This version resolves the merge issues resulting from the removal of
the nameidata parameter to inode_permission().
   - Moved the integrity_inode_permission() call from inode_permission()
     to vfs_inode_permission() and file_inode_permission().
   - Replaced the inode and nameidata parameters with file and path
     parameters to integrity_inode_permission().

This patch is a redesign of the integrity framework, which address a
number of issues, including
   - generalizing the measurement API beyond just inode measurements.
   - separation of the measurement into distinct collection, appraisal,
     and commitment phases, for greater flexibility.

Extended Verification Module(EVM) and the Integrity Measurement
Architecture(IMA) were originally implemented as an LSM module.  Based
on discussions on the LSM mailing list, a decision was made that the
LSM hooks should only be used to enforce mandatory access control
decisions and a new set of hooks should be defined specifically for
integrity.

EVM/IMA was limited to verifying and measuring a file's (i.e. an inode)
integrity and the metadata associated with it.  Current research is
looking into other types of integrity measurements. (i.e. "Linux kernel
integrity measurement using contextual inspection",  by Peter A. Loscocco,
Perry W. Wilson, J. Aaron Pendergrass, C. Durward McDonell,
http://doi.acm.org/10.1145/1314354.1314362). As a result, a requirement
of the new integrity framework is support for different types of integrity
measurements.

This patch provides an integrity framework(api and hooks) and placement
of the integrity hooks in the appropriate places in the fs directory.
Collecting, appraising, and storing of file and other types of integrity
data is supported.  Multiple integrity templates, which implement the
integrity API, may register themselves.  For now, only a single integrity
provider can register itself for the integrity hooks. (Support for multiple
providers registering themselves for the integrity hooks would require
some form of stacking.)

The six integrity hooks are:
   inode_permission, inode_alloc_integrity, inode_free_integrity,
   bprm_check_integrity, file_free_integrity, file_mmap

The five integrity API calls provided are:
   integrity_must_measure, integrity_collect_measurement,
   integrity_appraise_measurement, integrity_store_measurement,
   and integrity_display_template.

The type of integrity data being collected, appraised, stored, or
displayed is template dependent.

(Details on the calls and their exact arguments are in linux/integrity.h,
included in the patch.)

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
---
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e7bea3e..8a30e55 100644
--- a/Documentation/kernel-parameters.txt
+++ b/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.
+	INTEGRITY Integrity support 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.
@@ -878,6 +879,11 @@ and is between 256 and 4096 characters. It is defined in the file
 	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
 			Format: <irq>
 
+	integrity_audit= [INTEGRITY]
+                        Format: { "0" | "1" }
+                        0 -- disable integrity auditing messages.
+                        1 -- enable integrity auditing messages. (Default)
+
 	inttest=	[IA64]
 
 	iommu=		[x86]
diff --git a/fs/exec.c b/fs/exec.c
index 32993be..ec00043 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -45,6 +45,7 @@
 #include <linux/proc_fs.h>
 #include <linux/mount.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/syscalls.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
@@ -1204,6 +1205,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 	retval = security_bprm_check(bprm);
 	if (retval)
 		return retval;
+	retval = integrity_bprm_check(bprm);
+	if (retval)
+		return retval;
 
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
diff --git a/fs/file_table.c b/fs/file_table.c
index f45a449..8ba48aa 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/eventpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/mount.h>
@@ -272,6 +273,7 @@ void __fput(struct file *file)
 	if (file->f_op && file->f_op->release)
 		file->f_op->release(inode, file);
 	security_file_free(file);
+	integrity_file_free(file);
 	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
 		cdev_put(inode->i_cdev);
 	fops_put(file->f_op);
@@ -343,6 +345,7 @@ void put_filp(struct file *file)
 {
 	if (atomic_long_dec_and_test(&file->f_count)) {
 		security_file_free(file);
+		integrity_file_free(file);
 		file_kill(file);
 		file_free(file);
 	}
diff --git a/fs/inode.c b/fs/inode.c
index b6726f6..424de21 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -17,6 +17,7 @@
 #include <linux/hash.h>
 #include <linux/swap.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
@@ -143,13 +144,12 @@ static struct inode *alloc_inode(struct super_block *sb)
 		inode->i_cdev = NULL;
 		inode->i_rdev = 0;
 		inode->dirtied_when = 0;
-		if (security_inode_alloc(inode)) {
-			if (inode->i_sb->s_op->destroy_inode)
-				inode->i_sb->s_op->destroy_inode(inode);
-			else
-				kmem_cache_free(inode_cachep, (inode));
-			return NULL;
-		}
+		if (security_inode_alloc(inode))
+			goto out_free_inode;
+
+		/* allocate, attach and initialize an i_integrity */
+		if (integrity_inode_alloc(inode))
+			goto out_free_inode;
 
 		spin_lock_init(&inode->i_lock);
 		lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key);
@@ -184,12 +184,20 @@ static struct inode *alloc_inode(struct super_block *sb)
 		inode->i_mapping = mapping;
 	}
 	return inode;
+
+out_free_inode:
+	if (inode->i_sb->s_op->destroy_inode)
+		inode->i_sb->s_op->destroy_inode(inode);
+	else
+		kmem_cache_free(inode_cachep, (inode));
+	return NULL;
 }
 
 void destroy_inode(struct inode *inode) 
 {
 	BUG_ON(inode_has_buffers(inode));
 	security_inode_free(inode);
+	integrity_inode_free(inode);
 	if (inode->i_sb->s_op->destroy_inode)
 		inode->i_sb->s_op->destroy_inode(inode);
 	else
diff --git a/fs/namei.c b/fs/namei.c
index 4ea63ed..cd952b2 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -24,6 +24,7 @@
 #include <linux/fsnotify.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/syscalls.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
@@ -289,7 +290,14 @@ int inode_permission(struct inode *inode, int mask)
  */
 int vfs_permission(struct nameidata *nd, int mask)
 {
-	return inode_permission(nd->path.dentry->d_inode, mask);
+	int retval;
+
+	retval = inode_permission(nd->path.dentry->d_inode, mask);
+	if (retval)
+		return retval;
+	return integrity_inode_permission(NULL, &nd->path,
+					  mask & (MAY_READ | MAY_WRITE |
+						  MAY_EXEC));
 }
 
 /**
@@ -306,7 +314,14 @@ int vfs_permission(struct nameidata *nd, int mask)
  */
 int file_permission(struct file *file, int mask)
 {
-	return inode_permission(file->f_path.dentry->d_inode, mask);
+	int retval;
+
+	retval = inode_permission(file->f_path.dentry->d_inode, mask);
+	if (retval)
+		return retval;
+	return integrity_inode_permission(file, NULL,
+					  mask & (MAY_READ | MAY_WRITE |
+						  MAY_EXEC));
 }
 
 /*
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6272a39..90e8c38 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -123,6 +123,11 @@
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
 #define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
+#define AUDIT_INTEGRITY_DATA	    1800 /* Data integrity verification */
+#define AUDIT_INTEGRITY_METADATA    1801 /* Metadata integrity verification */
+#define AUDIT_INTEGRITY_STATUS	    1802 /* Integrity enable status */
+#define AUDIT_INTEGRITY_HASH	    1803 /* Integrity HASH type */
+#define AUDIT_INTEGRITY_PCR	    1804 /* PCR invalidation msgs */
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
@@ -440,6 +445,8 @@ extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 #define audit_get_loginuid(t) ((t)->loginuid)
 #define audit_get_sessionid(t) ((t)->sessionid)
 extern void audit_log_task_context(struct audit_buffer *ab);
+extern void audit_log_inode_context(struct audit_buffer *ab,
+					struct inode *inode);
 extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
 extern int audit_bprm(struct linux_binprm *bprm);
@@ -520,6 +527,7 @@ extern int audit_signals;
 #define audit_get_loginuid(t) (-1)
 #define audit_get_sessionid(t) (-1)
 #define audit_log_task_context(b) do { ; } while (0)
+#define audit_log_inode_context(b, a) do {  } while (0)
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m) ({ 0; })
 #define audit_bprm(p) ({ 0; })
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 580b513..342922f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -680,6 +680,9 @@ struct inode {
 #ifdef CONFIG_SECURITY
 	void			*i_security;
 #endif
+#ifdef CONFIG_INTEGRITY
+	void			*i_integrity;
+#endif
 	void			*i_private; /* fs or device private pointer */
 };
 
diff --git a/include/linux/integrity.h b/include/linux/integrity.h
new file mode 100644
index 0000000..d9c1d64
--- /dev/null
+++ b/include/linux/integrity.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005,2006,2007,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.
+ */
+
+#ifndef _LINUX_INTEGRITY_H
+#define _LINUX_INTEGRITY_H
+
+#include <linux/fs.h>
+#include <linux/audit.h>
+
+#ifdef CONFIG_INTEGRITY
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			const unsigned char *fname, char *op,
+			char *cause, int result);
+
+/*
+ * Integrity API calls:
+ *
+ * @collect_measurement:
+ *	Collect template specific measurement data.
+ *	@data contains template specific data used for collecting the
+ *	measurement.
+ * 	Return 0 if operation was successful.
+ *
+ * @appraise_measurement:
+ *	Appraise the integrity of the template specific measurement data.
+ *	@data contains template specific data used for appraising the
+ *	measurement.
+ * 	Return 0 if operation was successful.
+ *
+ * @store_measurement:
+ *	Store the template specific data.
+ *	@data contains template specific data used for storing the
+ *	measurement.
+ *
+ * @must_measure:
+ *	Measurement decision based on an integrity policy.
+ *	@data contains template specific data used for making policy
+ * 	decision.
+ * 	Return 0 if operation was successful.
+ *
+ * @display_template:
+ *	Display template specific data.
+ *
+ */
+
+enum integrity_show_type { INTEGRITY_SHOW_BINARY, INTEGRITY_SHOW_ASCII};
+
+struct template_operations {
+	int (*collect_measurement)(void *);
+	int (*appraise_measurement)(void *);
+	void (*store_measurement)(void *);
+	int (*must_measure)(void *);
+	void (*display_template)(struct seq_file *m, void *,
+				 enum integrity_show_type);
+};
+extern int integrity_register_template(const char *template_name,
+					const struct template_operations *ops);
+extern int integrity_unregister_template(const char *template_name);
+extern int integrity_find_template(const char *,
+				   const struct template_operations **ops);
+
+/*
+ * Integrity hooks:
+ *
+ * @bprm_check_integrity:
+ * 	This hook mediates the point when a search for a binary handler	will
+ * 	begin.  At this point, the OS protects against an executable file,
+ * 	already open for write, from being executed; and an executable file
+ * 	already open for execute, from being modified. So we can be certain
+ *	that any measurements(collect, appraise, store) done here are of
+ * 	the file being executed.
+ * 	@bprm contains the linux_binprm structure.
+ *	Return 0 if the hook is successful and permission is granted.
+ *
+ * @inode_alloc_integrity:
+ *	Allocate and attach an integrity structure to @inode->i_integrity.  The
+ * 	i_integrity field is initialized to NULL when the inode structure is
+ * 	allocated.
+ * 	@inode contains the inode structure.
+ * 	Return 0 if operation was successful.
+ *
+ * @inode_free_integrity:
+ *	@inode contains the inode structure.
+ * 	Deallocate the inode integrity structure and set @inode->i_integrity to
+ * 	NULL.
+ *
+ * @inode_permission:
+ *	This hook is called by the existing Linux vfs_permission and
+ *      file_permission functions, as a file is opened.  At this point,
+ *	measurements(collect, appraise, store) of files open for read
+ * 	can be made.
+ *	@file contains the file structure of the file being opened(may be NULL).
+ *	@path contains the path structure (may be NULL).
+ *	@mask contains the permission mask.
+ *	Return 0 if the hook is successful and permission is granted.
+ *
+ * @file_free_integrity:
+ *	Update the integrity xattr value as necessary.
+ * 	@file contains the file structure being closed.
+ *
+ * @file_mmap :
+ *	Measurements(collect, appraise, store) of files mmaped for EXEC
+ *	can be made.
+ *	@file contains the file structure of the file to map (may be NULL).
+ *	@prot contains the protection that will be applied by the kernel.
+ *	Return 0 if the hook is successful and permission is granted.
+ */
+
+enum lim_hooks {INODE_PERMISSION = 1, FILE_MMAP, BPRM_CHECK };
+
+struct integrity_operations {
+	int (*bprm_check_integrity) (struct linux_binprm *bprm);
+	int (*inode_alloc_integrity) (struct inode *inode);
+	void (*inode_free_integrity) (struct inode *inode);
+	int (*inode_permission) (struct file *file, struct path *path,
+				 int mask);
+	void (*file_free_integrity) (struct file *file);
+	int (*file_mmap) (struct file *file, unsigned long prot);
+};
+extern int register_integrity(const struct integrity_operations *ops);
+extern int unregister_integrity(const struct integrity_operations *ops);
+
+/* global variables */
+extern const struct integrity_operations *integrity_ops;
+
+
+int integrity_collect_measurement(const char *template_name, void *data);
+int integrity_appraise_measurement(const char *template_name, void *data);
+int integrity_must_measure(const char *template_name, void *data);
+int integrity_store_measurement(const char *template_name, void *data);
+
+int integrity_bprm_check(struct linux_binprm *bprm);
+int integrity_inode_alloc(struct inode *inode);
+void integrity_inode_free(struct inode *inode);
+int integrity_inode_permission(struct file *file, struct path *path,int mask);
+void integrity_file_free(struct file *file);
+int integrity_file_mmap(struct file *file, unsigned long prot);
+#else
+
+static inline int integrity_bprm_check(struct linux_binprm *bprm)
+{
+	return 0;
+}
+
+static inline int integrity_inode_alloc(struct inode *inode)
+{
+	return 0;
+}
+
+static inline void integrity_inode_free(struct inode *inode)
+{
+	return;
+}
+
+static inline int integrity_inode_permission(struct file *file,
+					     struct path *path, int mask);
+{
+	return 0;
+}
+
+static inline int integrity_file_permission(struct file *file, int mask)
+{
+	return 0;
+}
+
+static inline void integrity_file_free(struct file *file)
+{
+	return;
+}
+
+static inline int integrity_file_mmap(struct file *file, unsigned long prot)
+{
+	return 0;
+}
+#endif
+#endif
diff --git a/mm/mmap.c b/mm/mmap.c
index 245c3d6..c8b03c1 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/personality.h>
 #include <linux/security.h>
+#include <linux/integrity.h>
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
@@ -1046,6 +1047,9 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (error)
 		return error;
+	error = integrity_file_mmap(file, prot);
+	if (error)
+		return error;
 
 	return mmap_region(file, addr, len, flags, vm_flags, pgoff,
 			   accountable);
diff --git a/security/Kconfig b/security/Kconfig
index 5592939..61453fa 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -4,6 +4,8 @@
 
 menu "Security options"
 
+source security/integrity/Kconfig
+
 config KEYS
 	bool "Enable access key retention support"
 	help
diff --git a/security/Makefile b/security/Makefile
index f654260..b8132c9 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,3 +16,7 @@ obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
+
+# Object integrity file lists
+subdir-$(CONFIG_INTEGRITY)		+= integrity
+obj-$(CONFIG_INTEGRITY)			+= integrity/built-in.o
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
new file mode 100644
index 0000000..3c29050
--- /dev/null
+++ b/security/integrity/Kconfig
@@ -0,0 +1,24 @@
+#
+# Integrity configuration
+#
+
+menu "Integrity options"
+
+config INTEGRITY
+	bool "Enable different integrity models"
+	help
+	  This allows you to choose different integrity modules to be
+	  configured into your kernel.
+
+	  If you are unsure how to answer this question, answer N.
+
+config INTEGRITY_AUDIT
+	bool "Integrity audit boot parameter"
+	depends on INTEGRITY
+	default y
+	help
+	  This option adds a kernel parameter 'integrity_audit', which
+	  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
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
new file mode 100644
index 0000000..c9fb803
--- /dev/null
+++ b/security/integrity/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel integrity code
+#
+
+# Object file lists
+obj-$(CONFIG_INTEGRITY)			+= integrity.o integrity_audit.o
diff --git a/security/integrity/integrity.c b/security/integrity/integrity.c
new file mode 100644
index 0000000..7b6f993
--- /dev/null
+++ b/security/integrity/integrity.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2006,2007,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.
+ *
+ * File: integrity.c
+ * 	register integrity subsystem
+ * 	register integrity template
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/integrity.h>
+
+const struct integrity_operations *integrity_ops;
+EXPORT_SYMBOL(integrity_ops);
+
+#define TEMPLATE_NAME_LEN_MAX 12
+struct template_list_entry {
+	struct list_head template;
+	char template_name[TEMPLATE_NAME_LEN_MAX + 1];
+	const struct template_operations *template_ops;
+};
+static LIST_HEAD(integrity_templates);
+static DEFINE_MUTEX(integrity_templates_mutex);
+
+/**
+ * register_integrity - registers an integrity framework with the kernel
+ * @ops: a pointer to the struct security_options that is to be registered
+ *
+ * Perhaps in the future integrity module stacking will be necessary, but
+ * for the time being, this function permits only one integrity module to
+ * register itself with the kernel integrity subsystem.
+ *
+ * If another integrity module is already registered, an error code is
+ * returned. On success 0 is returned.
+ */
+int register_integrity(const struct integrity_operations *ops)
+{
+	if (integrity_ops != NULL)
+		return -EAGAIN;
+	integrity_ops = ops;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(register_integrity);
+
+/**
+ * unregister_integrity - unregisters an integrity framework from the kernel
+ * @ops: a pointer to the struct security_options that is to be registered
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int unregister_integrity(const struct integrity_operations *ops)
+{
+	if (ops != integrity_ops)
+		return -EINVAL;
+
+	integrity_ops = NULL;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(unregister_integrity);
+
+/**
+ * integrity_register_template - registers an integrity template with the kernel
+ * @template_name: a pointer to a string containing the template name.
+ * @template_ops: a pointer to the template functions
+ *
+ * Register a set of functions to collect, appraise, store, and display
+ * a template measurement, and a means to decide whether to do them.
+ * Unlike integrity modules, any number of templates may be registered.
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_register_template(const char *template_name,
+				const struct template_operations *template_ops)
+{
+	int template_len;
+	struct template_list_entry *entry;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&entry->template);
+
+	template_len = strlen(template_name);
+	if (template_len > TEMPLATE_NAME_LEN_MAX)
+		return -EINVAL;
+	strcpy(entry->template_name, template_name);
+	entry->template_ops = template_ops;
+
+	mutex_lock(&integrity_templates_mutex);
+	list_add_rcu(&entry->template, &integrity_templates);
+	mutex_unlock(&integrity_templates_mutex);
+	synchronize_rcu();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(integrity_register_template);
+
+/**
+ * integrity_unregister_template: unregister a template
+ * @template_name: a pointer to a string containing the template name.
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int integrity_unregister_template(const char *template_name)
+{
+	struct template_list_entry *entry;
+
+	mutex_lock(&integrity_templates_mutex);
+	list_for_each_entry(entry, &integrity_templates, template) {
+		if (strncmp(entry->template_name, template_name,
+			    strlen(entry->template_name)) == 0) {
+			list_del_rcu(&entry->template);
+			mutex_unlock(&integrity_templates_mutex);
+			synchronize_rcu();
+			kfree(entry);
+			return 0;
+		}
+	}
+	mutex_unlock(&integrity_templates_mutex);
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL_GPL(integrity_unregister_template);
+
+/**
+ * integrity_find_template - search the integrity_templates list
+ * @template_name: a pointer to a string containing the template name.
+ * @template_ops: a pointer to the template functions
+ *
+ * Called with an rcu_read_lock
+ * Returns 0 on success, -EINVAL on failure.
+ */
+int integrity_find_template(const char *template_name,
+			    const struct template_operations **template_ops)
+{
+	struct template_list_entry *entry;
+
+	list_for_each_entry_rcu(entry, &integrity_templates, template) {
+		if (strncmp(entry->template_name, template_name,
+			    strlen(entry->template_name)) == 0) {
+			*template_ops = entry->template_ops;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL_GPL(integrity_find_template);
+
+/* Start of the integrity API calls */
+
+/**
+ * integrity_collect_measurement - collect template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_collect_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->collect_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_collect_measurement);
+
+/**
+ * integrity_appraise_measurement - appraise template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure
+ */
+int integrity_appraise_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->appraise_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_appraise_measurement);
+
+/**
+ * integrity_store_measurement - store template specific measurement
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Store template specific integrity measurement.
+ */
+int integrity_store_measurement(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		template_ops->store_measurement(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_store_measurement);
+
+/**
+ * integrity_must_measure - measure decision based on template policy
+ * @template_name: a pointer to a string containing the template name.
+ * @data: pointer to template specific data
+ *
+ * Returns 0 on success, an error code on failure.
+ */
+int integrity_must_measure(const char *template_name, void *data)
+{
+	const struct template_operations *template_ops;
+	int rc;
+
+	rcu_read_lock();
+	rc = integrity_find_template(template_name, &template_ops);
+	if (rc == 0)
+		rc = template_ops->must_measure(data);
+	rcu_read_unlock();
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(integrity_must_measure);
+
+/* Start of the integrity Hooks */
+
+/* Hook used to measure executable file integrity. */
+int integrity_bprm_check(struct linux_binprm *bprm)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->bprm_check_integrity)
+		rc = integrity_ops->bprm_check_integrity(bprm);
+	return rc;
+}
+
+/* Allocate, attach and initialize an inode's i_integrity,
+ * if INTEGRITY is configured.
+ */
+int integrity_inode_alloc(struct inode *inode)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->inode_alloc_integrity)
+		rc = integrity_ops->inode_alloc_integrity(inode);
+	return rc;
+}
+
+/* Hook used to free an inode's i_integrity structure. */
+void integrity_inode_free(struct inode *inode)
+{
+	if (integrity_ops && integrity_ops->inode_free_integrity)
+		integrity_ops->inode_free_integrity(inode);
+}
+
+/* Hook used to measure a file's integrity. */
+int integrity_inode_permission(struct file *file, struct path *path, int mask)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->inode_permission)
+		rc = integrity_ops->inode_permission(file, path, mask);
+	return rc;
+}
+
+/* Hook used to update i_integrity data and integrity xattr values
+ * as necessary.
+ */
+void integrity_file_free(struct file *file)
+{
+	if (integrity_ops && integrity_ops->file_free_integrity)
+		integrity_ops->file_free_integrity(file);
+}
+
+/* Hook used to measure integrity of an mmapped file */
+int integrity_file_mmap(struct file *file, unsigned long prot)
+{
+	int rc = 0;
+
+	if (integrity_ops && integrity_ops->file_mmap)
+		rc = integrity_ops->file_mmap(file, prot);
+	return rc;
+}
diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c
new file mode 100644
index 0000000..2f8b835
--- /dev/null
+++ b/security/integrity/integrity_audit.c
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ *
+ * File: integrity_audit.c
+ * 	Audit calls for the integrity subsystem
+ */
+
+#include <linux/audit.h>
+#include <linux/fs.h>
+#include <linux/integrity.h>
+
+static int integrity_audit = 1;
+
+#ifdef CONFIG_INTEGRITY_AUDIT
+static int __init integrity_audit_setup(char *str)
+{
+	ulong audit;
+	int rc;
+	char *op;
+
+	rc = strict_strtoul(str, 10, &audit);
+	if (rc < 0 || audit > 1)
+		printk(KERN_INFO "integrity: invalid integrity_audit value\n");
+	else
+		integrity_audit = audit;
+
+	op = integrity_audit ? "integrity_audit_enabled" :
+	    "integrity_audit_not_enabled";
+	integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, NULL, op, 0);
+	return 1;
+}
+
+__setup("integrity_audit=", integrity_audit_setup);
+#endif
+
+void integrity_audit_msg(int audit_msgno, struct inode *inode,
+			 const unsigned char *fname, char *op,
+			 char *cause, int result)
+{
+	struct audit_buffer *ab;
+
+	if (!integrity_audit && result == 1)
+		return;
+
+	ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
+	audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u",
+			 current->pid, current->uid,
+			 audit_get_loginuid(current));
+	audit_log_task_context(ab);
+	switch (audit_msgno) {
+	case AUDIT_INTEGRITY_DATA:
+	case AUDIT_INTEGRITY_METADATA:
+	case AUDIT_INTEGRITY_PCR:
+		audit_log_format(ab, " op=%s cause=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_HASH:
+		audit_log_format(ab, " op=%s hash=%s", op, cause);
+		break;
+	case AUDIT_INTEGRITY_STATUS:
+	default:
+		audit_log_format(ab, " op=%s", op);
+	}
+	audit_log_format(ab, " comm=");
+	audit_log_untrustedstring(ab, current->comm);
+	if (fname) {
+		audit_log_format(ab, " name=");
+		audit_log_untrustedstring(ab, fname);
+	}
+	if (inode)
+		audit_log_format(ab, " dev=%s ino=%lu",
+				 inode->i_sb->s_id, inode->i_ino);
+	audit_log_format(ab, " res=%d", result);
+	audit_log_end(ab);
+}
-- 
1.5.5.1


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

end of thread, other threads:[~2008-10-07 18:30 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20080808184349.999902616@linux.vnet.ibm.com>
2008-08-08 18:55 ` [PATCH 1/4] integrity: TPM internel kernel interface Mimi Zohar
2008-08-09 18:46   ` Christoph Hellwig
2008-08-11 21:13     ` Mimi Zohar
2008-08-12 19:30       ` Christoph Hellwig
2008-08-12 20:57         ` Kenneth Goldman
2008-08-12 21:36           ` Alan Cox
2008-08-13 13:46             ` Kenneth Goldman
2008-08-13 13:40               ` Alan Cox
2008-08-13 14:45                 ` Christoph Hellwig
2008-08-13 16:39                 ` Kenneth Goldman
2008-08-12 23:16           ` Greg KH
2008-08-13 13:58             ` Kenneth Goldman
2008-08-13 16:56             ` Mimi Zohar
2008-08-14 11:12           ` Pavel Machek
2008-08-15 10:37             ` Peter Dolding
2008-08-15 18:50               ` Kenneth Goldman
2008-08-15 19:22                 ` Valdis.Kletnieks
2008-08-15 21:17                 ` Alan Cox
2008-08-18 15:01             ` Kenneth Goldman
2008-08-08 18:55 ` [PATCH 2/4] integrity: special fs magic Mimi Zohar
2008-08-08 19:04   ` Greg KH
2008-08-08 19:15     ` Greg KH
2008-08-08 19:50       ` Mimi Zohar
2008-08-08 23:07         ` Greg KH
2008-08-09 18:47       ` Christoph Hellwig
2008-08-10 13:48         ` Mimi Zohar
2008-08-08 19:36     ` Mimi Zohar
2008-08-08 23:15   ` Christoph Hellwig
2008-08-08 18:56 ` [PATCH 3/4] integrity: Linux Integrity Module(LIM) Mimi Zohar
2008-08-09 18:53   ` Christoph Hellwig
2008-08-10 13:52     ` Mimi Zohar
2008-08-11 17:02       ` Serge E. Hallyn
2008-08-11 19:08         ` Mimi Zohar
2008-08-11 19:56           ` Serge E. Hallyn
2008-08-12  8:41             ` Peter Dolding
2008-08-12 19:29               ` Christoph Hellwig
2008-08-13 10:44                 ` Peter Dolding
2008-08-13 14:11                   ` David Howells
2008-08-13 22:57                     ` Peter Dolding
2008-08-13 17:03             ` Mimi Zohar
2008-08-12 19:27         ` Christoph Hellwig
2008-08-12 21:19           ` Serge E. Hallyn
2008-08-13 17:03             ` Mimi Zohar
2008-08-12 19:25       ` Christoph Hellwig
2008-08-08 18:56 ` [PATCH 4/4] integrity: IMA as an integrity service provider Mimi Zohar
2008-08-08 20:06   ` Randy Dunlap
2008-10-07 18:00 [PATCH 0/4] integrity Mimi Zohar
2008-10-07 18:00 ` [PATCH 3/4] integrity: Linux Integrity Module(LIM) Mimi Zohar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox