integrity
Subsystems (10)
cover integrity
The first three patches address concerns raised on the mailing list. They apply cleanly to linux-2.6.28-rc5 and with minor offsets to security-testing-2.6/#next. The last patch is only for the security-testing-2.6/#next tree. It addresses credential merge issues.
- Merges the integrity radix tree patch into the existing integrity patches.
- Replaces integrity_nameidata_check() with integrity_path_check().
- Cleans up tget/tput callers and removed the null pointer test.
- Replaces remaining GFP_ATOMIC alloc with GFP_KERNEL.
- Replaces ima_iint_init() with RADIX_TREE macro.
Mimi Zohar (4):
integrity: TPM internel kernel interface
integrity: Linux Integrity Module(LIM)
integrity: IMA as an integrity service provider
integrity: replace task uid with cred uid
PATCH 1/4 integrity: TPM internel kernel interface
The internal TPM kernel interface did not protect itself from the removal of the TPM driver, while being used. We continue to protect the tpm_chip_list using the driver_lock as before, and are using an rcu lock to protect readers. The internal TPM kernel interface now protects itself from the driver being removed by incrementing the module reference count.
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
---
drivers/char/tpm/tpm.c +137 -3
@@ -1,11 +1,12 @@/* -* Copyright (C) 2004 IBM Corporation +* Copyright (C) 2004,2007,2008 IBM Corporation * * Authors: * Leendert van Doorn <[email protected]> * Dave Safford <[email protected]> * Reiner Sailer <[email protected]> * Kylene Hall <[email protected]> +* Debora Velarde <[email protected]> * * Maintained by: <[email protected]> *
@@ -28,6 +29,14 @@#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 <linux/rcupdate.h> +#include <asm/unaligned.h> #include "tpm.h" enum tpm_const {
@@ -50,6 +59,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 +377,7 @@ EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);/* * 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 +435,7 @@ out:mutex_unlock (&chip->tpm_mutex);return rc; } +EXPORT_SYMBOL_GPL (tpm_transmit);#define TPM_DIGEST_SIZE 20#define TPM_ERROR_SIZE 10
@@ -717,6 +728,7 @@ ssize_t tpm_show_temp_deactivated(struct device * dev, }EXPORT_SYMBOL_GPL (tpm_show_temp_deactivated); +#define READ_PCR_RESULT_SIZE 30static const u8 pcrread[] = {0 ,193 ,/* TPM_TAG_RQU_COMMAND */ 0 ,0 ,0 ,14 ,/* length */
@@ -772,6 +784,128 @@ out: }EXPORT_SYMBOL_GPL (tpm_show_pcrs); +/* +* tpm_chip_lookup - return tpm_chip for given chip number and type +* +* Must be called with rcu_read_lock. +*/ +static struct tpm_chip *tpm_chip_lookup (int chip_num,int chip_typ) +{ +struct tpm_chip *pos; +int rc; + +list_for_each_entry_rcu (pos, &tpm_chip_list, list) { + rc = (chip_num ==TPM_ANY_NUM || pos->dev_num == chip_num) + && (chip_typ ==TPM_ANY_TYPE ); +if (rc) +return pos; + } +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) +* +* The TPM driver should be built-in, but for whatever reason it +* isn't, protect against the chip disappearing, by incrementing +* the module usage count. +*/ +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; + +rcu_read_lock (); + chip =tpm_chip_lookup (chip_num, chip_id >>TPM_CHIP_TYPE_SHIFT ); +if (chip ==NULL ) { +rcu_read_unlock (); +return -ENODEV ; + } +if (!try_module_get (chip->dev->driver->owner)) { +rcu_read_unlock (); +return -ENODEV ; + } +rcu_read_unlock (); + +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 ); + +module_put (chip->dev->driver->owner); +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 +* +* The TPM driver should be built-in, but for whatever reason it +* isn't, protect against the chip disappearing, by incrementing +* the module usage count. +*/ +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; + +rcu_read_lock (); + chip =tpm_chip_lookup (chip_num, chip_id >>TPM_CHIP_TYPE_SHIFT ); +if (chip ==NULL ) { +rcu_read_unlock (); +return -ENODEV ; + } +if (!try_module_get (chip->dev->driver->owner)) { +rcu_read_unlock (); +return -ENODEV ; + } +rcu_read_unlock (); + +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 )); + +module_put (chip->dev->driver->owner); +return rc; +} +EXPORT_SYMBOL_GPL (tpm_pcr_extend); +#define READ_PUBEK_RESULT_SIZE 314static const u8 readpubek[] = {0 ,193 ,/* TPM_TAG_RQU_COMMAND */
drivers/char/tpm/tpm.h +3 -1
@@ -1,5 +1,5 @@/* -* Copyright (C) 2004 IBM Corporation +* Copyright (C) 2004, 2007, 2008 IBM Corporation * * Authors: * Leendert van Doorn <[email protected]>
@@ -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_chip *);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 *);
drivers/char/tpm/tpm_tis.c +3 -0
@@ -642,6 +642,9 @@ static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)static struct pnp_driver tis_pnp_driver = { .name ="tpm_tis" , + .driver = { + .owner =THIS_MODULE , + }, .id_table = tpm_pnp_tbl, .probe = tpm_tis_pnp_init, .suspend = tpm_tis_pnp_suspend,
include/linux/tpm.h new file +49 -0
49 lines not on this page · raw message
Signature · 1 line
1.5.6.5
PATCH 2/4 integrity: Linux Integrity Module(LIM)
In reply to Mimi ZoharThis version resolves the merge issues resulting from the removal of the nameidata parameter to inode_permission(), by moving the integrity_inode_permission() call from inode_permission() to may_open(), and renaming the hook to integrity_path_check(). The path is needed in order to open and read the file, so that the file can be hashed(a cryptographically strong checksum.)
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:
path_check_integrity, 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.)
---
Documentation/kernel-parameters.txt +6 -0
@@ -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.
@@ -894,6 +895,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 -- integrity auditing messages. (Default) + 1 -- enable informational integrity auditing messages. + inttest= [IA64] iommu= [x86]
fs/exec.c +7 -0
@@ -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>
@@ -129,6 +130,9 @@ asmlinkage long sys_uselib(const char __user * library) error =vfs_permission (&nd,MAY_READ |MAY_EXEC |MAY_OPEN );if (error) goto exit; + error =integrity_path_check (&nd.path,MAY_READ |MAY_EXEC |MAY_OPEN ); +if (error) + goto exit; file =nameidata_to_filp (&nd,O_RDONLY |O_LARGEFILE ); error =PTR_ERR (file);
@@ -1199,6 +1203,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. */
fs/file_table.c +3 -0
@@ -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>
@@ -276,6 +277,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);
@@ -347,6 +349,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); }
fs/inode.c +16 -6
@@ -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,12 +144,13 @@ 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)) { +security_inode_free (inode); + goto out_free_inode; }spin_lock_init (&inode->i_lock);
@@ -185,12 +187,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
fs/namei.c +6 -0
@@ -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>
@@ -1523,6 +1524,11 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) error =vfs_permission (nd, acc_mode);if (error)return error; + + error =integrity_path_check (&nd->path, acc_mode + & (MAY_READ |MAY_WRITE |MAY_EXEC )); +if (error) +return error;/* * An append-only file must be opened in append mode for writing. */
include/linux/audit.h +5 -0
@@ -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. */
include/linux/integrity.h new file +166 -0
166 lines not on this page · raw message
mm/mmap.c +4 -0
@@ -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>
@@ -1050,6 +1051,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);
security/Kconfig +2 -0
@@ -126,5 +126,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR source security/selinux/Kconfig source security/smack/Kconfig +source security/integrity/Kconfig + endmenu
security/Makefile +4 -0
@@ -17,3 +17,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
security/integrity/Kconfig new file +24 -0
@@ -0,0 +1,24 @@ +# +# Integrity configuration +# + +config INTEGRITY + bool "Enable different integrity models" + help + This allows you to choose different integrity modules to be + configured into your kernel. Integrity models can collect, + verify, and record measurements, such as of a file's data + and metadata before it is read or executed. + + If you are unsure how to answer this question, answer N. + +config INTEGRITY_AUDIT + bool "Integrity audit boot parameter" + depends on INTEGRITY + default n + help + This option adds a kernel parameter 'integrity_audit', which + allows informational integrity auditing messages to be enabled + at boot. If this option is selected, informational integrity + auditing messages can be enabled with 'integrity_audit=1' on + the kernel command line.
security/integrity/Makefile new file +6 -0
@@ -0,0 +1,6 @@ +# +# Makefile for the kernel integrity code +# + +# Object file lists +obj-$(CONFIG_INTEGRITY) += integrity.o integrity_audit.o
security/integrity/integrity.c new file +313 -0
313 lines not on this page · raw message
security/integrity/integrity.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* Copyright (C) 2008 IBM Corporation +* Author: Mimi Zohar <[email protected]> +* +* 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. +*/ + +#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; +atomic_t refcount; +}; + +static inline void tget (struct template_list_entry *entry) +{ +atomic_inc (&entry->refcount); +} + +static inline void tput (struct template_list_entry *entry) +{ +if (atomic_dec_and_test (&entry->refcount)) +kfree (entry); +} + +extern int integrity_find_template (const char *, +struct template_list_entry **entry);
security/integrity/integrity_audit.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
1.5.6.5
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Ok, the API looks sane to me. But one big question: any reason you don't just directly call into your implementation instead of all these odd hooks? This seems to be a lot of overhead just for making the code less readable..
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 5 lines · Christoph Hellwig
Ok, the API looks sane to me. But one big question: any reason you don't just directly call into your implementation instead of all these odd hooks? This seems to be a lot of overhead just for making the code less readable..
The consensus in the (insane) security community was to have an interface with selectable modules similar to LSM and its modules, so that users could easily choose among a set of integrity providers.
dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 3 lines · david safford
The consensus in the (insane) security community was to have an interface with selectable modules similar to LSM and its modules, so that users could easily choose among a set of integrity providers.
So what other integrity provider is there waiting to be merged? Unless there is a realistic mid-term candidate it's just pure bloat, and we can introduce an abstraction once it's actually needed.
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 9 lines · Christoph Hellwig
Quoted 3 lines · david safford
The consensus in the (insane) security community was to have an interface with selectable modules similar to LSM and its modules, so that users could easily choose among a set of integrity providers.
So what other integrity provider is there waiting to be merged? Unless there is a realistic mid-term candidate it's just pure bloat, and we can introduce an abstraction once it's actually needed.
IMA tries to be generic, but it is still oriented around the Trusted Computing Group concept of hardware anchored lists of file measurements. We know of other projects looking at measurements of things that are not files, such as introspection of process memory invariants, and other integrity models not anchored in TCG hardware, such as public key signed files. I don't really know how close these other projects are to submission, but when this was reviewed on the LSM mailing list, everyone agreed with the abstraction. Hopefully some of the other interested people will chime in here.
dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
In reply to Mimi ZoharQuoted 8 lines · Mimi Zohar
security/integrity/integrity.c new file +6
-0+int integrity_find_template (const char *template_name, +struct template_list_entry **template_entry) +{ +struct template_list_entry *entry; + +list_for_each_entry_rcu (entry, &integrity_templates, template){
security/integrity/integrity.c line 147
Quoted 9 lines
security/integrity/integrity.c new file +9
-0+if (strncmp (entry->template_name, template_name, +strlen (entry->template_name)) ==0 ) { + *template_entry = entry; +return 0 ; + } + } +return -EINVAL ; +} +EXPORT_SYMBOL_GPL (integrity_find_template);
Is this an appropriate place for an ERR_PTR() to get used?
-- Dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
In reply to Mimi Zoharsecurity/integrity/integrity.c line 167
Quoted 6 lines · Mimi Zohar
security/integrity/integrity.c new file +5
-0+rcu_read_lock (); + rc =integrity_find_template (template_name, &template_entry); +if (rc ==0 ) +tget (template_entry); +rcu_read_unlock ();
This little nugget is repeated over and over. How about an integrity_find_get_template()?
-- Dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 8 lines · Dave Hansen
security/integrity/integrity.c line 167
Quoted 6 lines · Mimi Zohar
security/integrity/integrity.c new file +5
-0+rcu_read_lock (); + rc =integrity_find_template (template_name, &template_entry); +if (rc ==0 ) +tget (template_entry); +rcu_read_unlock ();
Quoted 4 lines
This little nugget is repeated over and over. How about an
integrity_find_get_template()?-- Dave
Sounds good.
Mimi
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
In reply to Mimi Zoharsecurity/integrity/integrity.h line 27
Quoted 11 lines · Mimi Zohar
security/integrity/integrity.h new file +10
-0+static inline void tget (struct template_list_entry *entry) +{ +atomic_inc (&entry->refcount); +} + +static inline void tput (struct template_list_entry *entry) +{ +if (atomic_dec_and_test (&entry->refcount)) +kfree (entry); +}
Seems like a good place for a kref.
-- Dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 15 lines · Dave Hansen
security/integrity/integrity.h line 27
Quoted 11 lines · Mimi Zohar
security/integrity/integrity.h new file +10
-0+static inline void tget (struct template_list_entry *entry) +{ +atomic_inc (&entry->refcount); +} + +static inline void tput (struct template_list_entry *entry) +{ +if (atomic_dec_and_test (&entry->refcount)) +kfree (entry); +}Seems like a good place for a kref.
Quoted 1 line
-- Dave
Thanks!
Mimi
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
In reply to Mimi Zoharsecurity/integrity/integrity_audit.c line 26
Quoted 11 lines · Mimi Zohar
security/integrity/integrity_audit.c new file +10
-0+static int integrity_audit; + +#ifdef CONFIG_INTEGRITY_AUDIT +static int __init integrity_audit_setup (char *str) +{ +ulong audit; +int rc; +char *op; + + rc =strict_strtoul (str,0 , &audit);
I think we usually write out 'unsigned long'.
-- Dave
Re: [PATCH 2/4] integrity: Linux Integrity Module(LIM)
Quoted 15 lines · Dave Hansen
security/integrity/integrity_audit.c line 26
Quoted 11 lines · Mimi Zohar
security/integrity/integrity_audit.c new file +10
-0+static int integrity_audit; + +#ifdef CONFIG_INTEGRITY_AUDIT +static int __init integrity_audit_setup (char *str) +{ +ulong audit; +int rc; +char *op; + + rc =strict_strtoul (str,0 , &audit);I think we usually write out 'unsigned long'.
Quoted 1 line
-- Dave
Ok
Mimi
PATCH 3/4 integrity: IMA as an integrity service provider
In reply to Mimi ZoharThis is a re-release of Integrity Measurement Architecture(IMA) as an independent Linunx Integrity Module(LIM) service provider.
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, nameidata_check_integrity, file_mmap 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.
---
Documentation/ABI/testing/ima_policy new file +61 -0
@@ -0,0 +1,61 @@ +What: security/ima/policy +Date: May 2008 +Contact: Mimi Zohar <[email protected]> +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 the securityfs file 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 file 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 + + 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: + # SELINUX_MAGIC + dont_measure fsmagic=0xF97CFF8C + + 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
Documentation/kernel-parameters.txt +5 -0
@@ -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.
@@ -878,6 +879,10 @@ and is between 256 and 4096 characters. It is defined in the file ihash_entries= [KNL] Set number of hash buckets for inode cache. + ima_hash= [IMA] runtime ability to define hash crypto algorithm. + Format: { "MD5" | "SHA1" } + Default is "SHA1". + in2000= [HW,SCSI] See header of drivers/scsi/in2000.c.
include/linux/ima.h new file +46 -0
46 lines not on this page · raw message
security/Kconfig +2 -1
@@ -55,7 +55,8 @@ config SECURITYFS bool "Enable the securityfs filesystem" help This will build the securityfs filesystem. It is currently used by - the TPM bios character driver. It is not used by SELinux or SMACK. + the TPM bios character driver and IMA, an integrity provider. It + is not used by SELinux or SMACK. If you are unsure how to answer this question, answer N.
security/integrity/Kconfig +2 -0
@@ -22,3 +22,5 @@ config INTEGRITY_AUDIT at boot. If this option is selected, informational integrity auditing messages can be enabled with 'integrity_audit=1' on the kernel command line. + +source security/integrity/ima/Kconfig
security/integrity/Makefile +1 -0
@@ -4,3 +4,4 @@ # Object file lists obj-$(CONFIG_INTEGRITY) += integrity.o integrity_audit.o +obj-$(CONFIG_IMA) += ima/
security/integrity/ima/Kconfig new file +48 -0
48 lines not on this page · raw message
security/integrity/ima/Makefile new file +9 -0
@@ -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 ima_iint.o
security/integrity/ima/ima.h new file +198 -0
198 lines not on this page · raw message
security/integrity/ima/ima_api.c new file +420 -0
420 lines not on this page · raw message
security/integrity/ima/ima_crypto.c new file +147 -0
147 lines not on this page · raw message
security/integrity/ima/ima_fs.c new file +488 -0
488 lines not on this page · raw message
security/integrity/ima/ima_iint.c new file +63 -0
63 lines not on this page · raw message
security/integrity/ima/ima_init.c new file +105 -0
105 lines not on this page · raw message
security/integrity/ima/ima_main.c new file +331 -0
331 lines not on this page · raw message
security/integrity/ima/ima_policy.c new file +334 -0
334 lines not on this page · raw message
security/integrity/ima/ima_queue.c new file +124 -0
124 lines not on this page · raw message
Signature · 1 line
1.5.6.5
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
Ok, after the API is sorted out I had a quick looks at this patch.
The first very odd thing is the data strucutures:
include/linux/ima.h line 27
Quoted 10 lines
include/linux/ima.h new file +10
-0+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; +};
You can always get from a file to a path, from a path to a dentry, from a dentry to and inode and from a path to some defintion of a filename. So a lot of things here seems very redundant.
When looking at how it's used it's acually even worse. AFAICS the code would be a lot cleaner if you'd just kill struct ima_args_data and the odd pass arguments as void pointers obsfucations and just pass the file/path + mask directly to the lower level functions.
That's also help killing things like ima_store_measurement which do entirely different things depending on idata->type.
security/integrity/ima/ima_api.c line 239
Quoted 12 lines
security/integrity/ima/ima_api.c new file +12
-0+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 */ +}
This could just be an
if (!S_ISREG(inode->i_mode))
in the caller..
security/integrity/ima/ima_crypto.c line 31
Quoted 2 lines
security/integrity/ima/ima_crypto.c new file +2
-0+static int update_file_hash (struct file *f,struct path *path, +struct hash_desc *desc)
Please split this into a update_file_hash that always operates on a struct file, and a wrapper around it that creates the struct file for the cases that needs it.
Quoted 12 lines
security/integrity/ima/ima_main.c new file +12
-0+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) + data->dentry = dentry = file->f_dentry;
security/integrity/ima/ima_main.c line 82
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+ +if (path) { +if (!dentry) + data->dentry = dentry = path->dentry; + } +if (dentry) + data->inode = dentry->d_inode; + +return ; +}
You have two different callers for this, either file NULL or path NULL but never neither or both. So just do the setup in the callers and do the right thing there. (and please kill the inode member, it's entirely superflous)
security/integrity/ima/ima_main.c line 96
Quoted 7 lines
security/integrity/ima/ima_main.c new file +7
-0+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 ;
No, it can't.
Quoted 12 lines
security/integrity/ima/ima_main.c new file +11
-0+ +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)) { +* Returns 0 on success, -ENOMEM on failure +*/ +static int ima_inode_alloc_integrity (struct inode *inode) +{ +return ima_iint_insert (inode);
security/integrity/ima/ima_main.c line 138
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+} + +/** +* ima_inode_free_integrity - free the integrity structure +* @inode: the inode structure +*/ +static void ima_inode_free_integrity (struct inode *inode) +{ +ima_iint_delete (inode); +}
Why these wrappers?
security/integrity/ima/ima_main.c line 171
Quoted 4 lines
security/integrity/ima/ima_main.c new file +4
-0+/* The file name is only a hint. */ + dentry = path->dentry; + data->filename = (!dentry->d_name.name) ? (char *)dentry->d_iname : + (char *)dentry->d_name.name;
d_iname is the internal storage for d_name, always use d_name only.
security/integrity/ima/ima_main.c line 174
Quoted 2 lines
security/integrity/ima/ima_main.c new file +2
-0+/* Invalidate PCR, if a measured file is already open for read */ +if ((mask ==MAY_WRITE ) || (mask ==MAY_APPEND )) {
MAY_APPEND is ORed into a mask, but never used standalone.
security/integrity/ima/ima_main.c line 202
Quoted 11 lines
security/integrity/ima/ima_main.c new file +10
-0+if (!rc) { +if (atomic_read (&(data->dentry->d_count)) -1 > +atomic_read (&(inode->i_writecount))) +ima_add_violation (inode, data->filename, +"invalid_pcr" ,"ToMToU" ); + } +if (atomic_read (&(inode->i_writecount)) >0 ) +ima_add_violation (inode, data->filename, +"invalid_pcr" , +"open_writers" );
All these d_count and i_writecount access needs a lot of explanation, they certainly don't make sense as-is, but I'd like to find out what you're actually trying to do here.
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (!file || !file->f_dentry) + return rc;
Can't happen.
security/integrity/ima/ima_policy.c line 29
Quoted 2 lines
security/integrity/ima/ima_policy.c new file +2
-0+#define audit_type (type) AUDIT_ ##type +#define lsm_type (type) LSM_ ##type
Just spelling out the constants would be a lot more readable..
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines
security/integrity/ima/ima_main.c new file +6
-0+if (!rc) { +if (atomic_read (&(data->dentry->d_count)) -1 > +atomic_read (&(inode->i_writecount))) +ima_add_violation (inode, data->filename, +"invalid_pcr" ,"ToMToU" ); + }
Quoted 8 lines
security/integrity/ima/ima_main.c line 202
Quoted 4 lines
security/integrity/ima/ima_main.c new file +4
-0+if (atomic_read (&(inode->i_writecount)) >0 ) +ima_add_violation (inode, data->filename, +"invalid_pcr" , +"open_writers" );All these
d_countandi_writecountaccess needs a lot of explanation, they certainly don't make sense as-is, but I'd like to find out what you're actually trying to do here.
The OS protects against an executable file, already open for write, from being executed; and an executable file, open for execute, from being modified. In the same vein, we want to know that the file measured is the same file read, that it hasn't been modified. So, if a file already open for read is then opened for write, we log it with a "Time of Measure, Time of Use" error (ToMToU) and invalidate the PCR. Or, if a file already open for write is then opened for read, we log the fact that the file could change while being read and invalidate the PCR.
This is important when measuring configuration files, shell scripts (not measured in brpm_check_integrity which are protected by the OS), and files imported/included by scripts.
Mimi
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
In reply to Christoph HellwigQuoted 19 lines · Christoph Hellwig
Ok, after the API is sorted out I had a quick looks at this patch.
The first very odd thing is the data strucutures:
include/linux/ima.h line 27
Quoted 10 lines
include/linux/ima.h new file +10
-0+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; +};You can always get from a file to a path, from a path to a dentry, from a dentry to and inode and from a path to some defintion of a filename. So a lot of things here seems very redundant.
Quoted 7 lines
When looking at how it's used it's acually even worse. AFAICS the code would be a lot cleaner if you'd just kill struct
ima_args_dataand the odd pass arguments as void pointers obsfucations and just pass the file/path + mask directly to the lower level functions.That's also help killing things like
ima_store_measurementwhich do entirely different things depending onidata->type.
hm, looking into it.
Quoted 15 lines
security/integrity/ima/ima_api.c line 239
Quoted 12 lines
security/integrity/ima/ima_api.c new file +12
-0+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 */ +}This could just be an
Quoted 3 lines
if (!S_ISREG(inode->i_mode))in the caller..
Done.
Quoted 6 lines
security/integrity/ima/ima_crypto.c line 31
Quoted 2 lines
security/integrity/ima/ima_crypto.c new file +2
-0+static int update_file_hash (struct file *f,struct path *path, +struct hash_desc *desc)Please split this into a
update_file_hashthat always operates on a struct file, and a wrapper around it that creates the struct file for the cases that needs it.
Ok.
Quoted 54 lines
Quoted 12 lines
security/integrity/ima/ima_main.c new file +12
-0+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) + data->dentry = dentry = file->f_dentry;security/integrity/ima/ima_main.c line 82
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+ +if (path) { +if (!dentry) + data->dentry = dentry = path->dentry; + } +if (dentry) + data->inode = dentry->d_inode; + +return ; +}You have two different callers for this, either file NULL or path NULL but never neither or both. So just do the setup in the callers and do the right thing there. (and please kill the inode member, it's entirely superflous)
security/integrity/ima/ima_main.c line 96
Quoted 7 lines
security/integrity/ima/ima_main.c new file +7
-0+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 ;No, it can't.
Quoted 16 lines
security/integrity/ima/ima_main.c new file +15
-0+ +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)) { +* Returns 0 on success, -ENOMEM on failure +*/ +static int ima_inode_alloc_integrity (struct inode *inode) +{ +return ima_iint_insert (inode); +} + +/** +* ima_inode_free_integrity - free the integrity structure
Quoted 8 lines
security/integrity/ima/ima_main.c line 138
Quoted 6 lines
+ * @inode: the inode structure
+ */security/integrity/ima/ima_main.c new file +4
-0+static void ima_inode_free_integrity (struct inode *inode) +{ +ima_iint_delete (inode); +}Why these wrappers?
You're right. I'll remove these routines and assign ima_iint_insert()/delete() directly in ima_integrity_ops.
Quoted 6 lines
security/integrity/ima/ima_main.c line 171
Quoted 4 lines
security/integrity/ima/ima_main.c new file +4
-0+/* The file name is only a hint. */ + dentry = path->dentry; + data->filename = (!dentry->d_name.name) ? (char *)dentry->d_iname : + (char *)dentry->d_name.name;
d_inameis the internal storage ford_name, always used_nameonly.
ok
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ if (!file || !file->f_dentry) + return rc;Can't happen.
Will remove test.
Quoted 4 lines
security/integrity/ima/ima_policy.c line 29
Quoted 2 lines
security/integrity/ima/ima_policy.c new file +2
-0+#define audit_type (type) AUDIT_ ##type +#define lsm_type (type) LSM_ ##typeJust spelling out the constants would be a lot more readable..
ok
Mimi
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
In reply to Mimi ZoharQuoted 8 lines · Mimi Zohar
+ /* Invalidate PCR, if a measured file is already open for read
*/security/integrity/ima/ima_main.c new file +5
-0+if ((mask ==MAY_WRITE ) || (mask ==MAY_APPEND )) { +int mask_sav = data->mask; +int rc; + + data->mask =MAY_READ ;
security/integrity/ima/ima_main.c line 188
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+ 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; + }
Following up on Christoph's comment...
I'm worried that this calculation isn't very precise. The calculation that you're trying to come up with here is the number of opens (d_count) vs. the number of writers (i_writecount). When they don't match, you know that the new open is the first write, and you must 'invalidate the PCR'?
There are a number of things that elevate d_count, and it is a lot more than just an open() that can do it. Is that OK?
-- Dave
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
Quoted 28 lines · Dave Hansen
Quoted 8 lines · Mimi Zohar
+ /* Invalidate PCR, if a measured file is already open for read
*/security/integrity/ima/ima_main.c new file +5
-0+if ((mask ==MAY_WRITE ) || (mask ==MAY_APPEND )) { +int mask_sav = data->mask; +int rc; + + data->mask =MAY_READ ;security/integrity/ima/ima_main.c line 188
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+ 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; + }Following up on Christoph's comment...
I'm worried that this calculation isn't very precise. The calculation that you're trying to come up with here is the number of opens (
d_count) vs. the number of writers (i_writecount). When they don't match, you know that the new open is the first write, and you must 'invalidate the PCR'?
Quoted 6 lines
There are a number of things that elevate
d_count, and it is a lot more than just anopen()that can do it. Is that OK?-- Dave
From an integrity perspective, a file measurement might be invalidated
unnecessarily, but it is safe. For any file when opened for write, while having an existing reader, will cause the file measurement to be invalidated. Can you give examples of things, other than open(), that elevate d_count?
Is there a different, better way to determine if there are any readers?
Thanks!
Mimi
Re: [PATCH 3/4] integrity: IMA as an integrity service provider
Quoted 29 lines · Mimi Zohar
Quoted 28 lines · Dave Hansen
Quoted 8 lines · Mimi Zohar
+ /* Invalidate PCR, if a measured file is already open for read
*/security/integrity/ima/ima_main.c new file +5
-0+if ((mask ==MAY_WRITE ) || (mask ==MAY_APPEND )) { +int mask_sav = data->mask; +int rc; + + data->mask =MAY_READ ;security/integrity/ima/ima_main.c line 188
Quoted 10 lines
security/integrity/ima/ima_main.c new file +10
-0+ 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; + }Following up on Christoph's comment...
I'm worried that this calculation isn't very precise. The calculation that you're trying to come up with here is the number of opens (
d_count) vs. the number of writers (i_writecount). When they don't match, you know that the new open is the first write, and you must 'invalidate the PCR'?
Quoted 8 lines
Quoted 4 lines
There are a number of things that elevate
d_count, and it is a lot more than just anopen()that can do it. Is that OK?From an integrity perspective, a file measurement might be invalidated
unnecessarily, but it is safe. For any file when opened for write, while having an existing reader, will cause the file measurement to be invalidated. Can you give examples of things, other than
open(), that elevated_count?
Just do a little search for dget(). There are plenty of places that we'll do a lookup (and a dget), realize that we can't complete an operation (say O_RDWR on a 400 file), then dput() the dentry. If you look at dput at the wrong time, you could mistake that for an *actual* open.
Are you holding any locks here? If not, it is completely conceivable that you do the atomic_read(d_count)=100, then by the time you do the aomtic_read(i_writecount), 90 of those references have been dput()'d.
Quoted 1 line
Is there a different, better way to determine if there are any readers?
I think you're looking at it from the wrong angle. If you have a writer, does it matter whether there are any readers? You should just unconditionally invalidate the integrity measurement.
-- Dave
PATCH 4/4 integrity: replace task uid with cred uid
In reply to Mimi ZoharThis patch addresses the credential merge changes in the security-testing-2.6/next tree.
---
security/integrity/ima/ima_crypto.c +1 -1
@@ -44,7 +44,7 @@ static int update_file_hash(struct file *f, struct path *path, rc = -EINVAL ; goto out; } - file =dentry_open (de, mnt,O_RDONLY ); + file =dentry_open (de, mnt,O_RDONLY , current->cred);if (IS_ERR (file)) {ima_info ("%s dentry_open failed\n" , de->d_name.name); rc =PTR_ERR (file);
security/integrity/ima/ima_policy.c +1 -1
@@ -95,7 +95,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,if ((rule->flags &IMA_FSMAGIC ) && rule->fsmagic != inode->i_sb->s_magic)return false; -if ((rule->flags &IMA_UID ) && rule->uid != tsk->uid) +if ((rule->flags &IMA_UID ) && rule->uid != tsk->cred->uid)return false;for (i =0 ; i <MAX_LSM_RULES ; i++) {int rc;
security/integrity/integrity_audit.c +1 -1
@@ -49,7 +49,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, 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, + current->pid, current->cred->uid,audit_get_loginuid (current));audit_log_task_context (ab);switch (audit_msgno) {
Signature · 1 line
1.5.6.5
My worry:
36 files changed, 3250 insertions(+), 14 deletions(-)
Can you find any better way to split this up? 79k is still pretty huge for one patch. Were you just trying to get under the LKML limit? ;)
Documentation/kernel-parameters.txt | 5 b/Documentation/ABI/testing/ima_policy | 61 ++++ b/Documentation/kernel-parameters.txt | 6 b/drivers/char/tpm/tpm.c | 140 +++++++++ b/drivers/char/tpm/tpm.h | 4 b/drivers/char/tpm/tpm_tis.c | 3 b/fs/exec.c | 7 b/fs/file_table.c | 3 b/fs/inode.c | 22 + b/fs/namei.c | 6 b/include/linux/audit.h | 5 b/include/linux/ima.h | 46 +++ b/include/linux/integrity.h | 166 +++++++++++ b/include/linux/tpm.h | 49 +++ b/mm/mmap.c | 4 b/security/Kconfig | 2 b/security/Makefile | 4 b/security/integrity/Kconfig | 24 + b/security/integrity/Makefile | 6 b/security/integrity/ima/Kconfig | 48 +++ b/security/integrity/ima/Makefile | 9 b/security/integrity/ima/ima.h | 198 +++++++++++++ b/security/integrity/ima/ima_api.c | 420 ++++++++++++++++++++++++++++ b/security/integrity/ima/ima_crypto.c | 149 ++++++++++ b/security/integrity/ima/ima_fs.c | 488 +++++++++++++++++++++++++++++++++ b/security/integrity/ima/ima_iint.c | 63 ++++ b/security/integrity/ima/ima_init.c | 105 +++++++ b/security/integrity/ima/ima_main.c | 331 ++++++++++++++++++++++ b/security/integrity/ima/ima_policy.c | 336 ++++++++++++++++++++++ b/security/integrity/ima/ima_queue.c | 124 ++++++++ b/security/integrity/integrity.c | 313 +++++++++++++++++++++ b/security/integrity/integrity.h | 30 ++ b/security/integrity/integrity_audit.c | 81 +++++ security/Kconfig | 3 security/integrity/Kconfig | 2 security/integrity/Makefile | 1 36 files changed, 3250 insertions(+), 14 deletions(-)
-- Dave