aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /security/integrity
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/Kconfig1
-rw-r--r--security/integrity/ima/ima.h6
-rw-r--r--security/integrity/ima/ima_api.c5
-rw-r--r--security/integrity/ima/ima_audit.c1
-rw-r--r--security/integrity/ima/ima_crypto.c1
-rw-r--r--security/integrity/ima/ima_fs.c1
-rw-r--r--security/integrity/ima/ima_iint.c86
-rw-r--r--security/integrity/ima/ima_init.c1
-rw-r--r--security/integrity/ima/ima_main.c310
-rw-r--r--security/integrity/ima/ima_policy.c10
-rw-r--r--security/integrity/ima/ima_queue.c1
11 files changed, 171 insertions, 252 deletions
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 53d9764e8f09..3d7846de8069 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -3,6 +3,7 @@
3config IMA 3config IMA
4 bool "Integrity Measurement Architecture(IMA)" 4 bool "Integrity Measurement Architecture(IMA)"
5 depends on ACPI 5 depends on ACPI
6 depends on SECURITY
6 select SECURITYFS 7 select SECURITYFS
7 select CRYPTO 8 select CRYPTO
8 select CRYPTO_HMAC 9 select CRYPTO_HMAC
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 165eb5397ea5..47fb65d1fcbd 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -65,7 +65,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
65 const char *cause, int result, int info); 65 const char *cause, int result, int info);
66 66
67/* Internal IMA function definitions */ 67/* Internal IMA function definitions */
68void ima_iintcache_init(void);
69int ima_init(void); 68int ima_init(void);
70void ima_cleanup(void); 69void ima_cleanup(void);
71int ima_fs_init(void); 70int ima_fs_init(void);
@@ -97,7 +96,6 @@ static inline unsigned long ima_hash_key(u8 *digest)
97 96
98/* iint cache flags */ 97/* iint cache flags */
99#define IMA_MEASURED 1 98#define IMA_MEASURED 1
100#define IMA_IINT_DUMP_STACK 512
101 99
102/* integrity data associated with an inode */ 100/* integrity data associated with an inode */
103struct ima_iint_cache { 101struct ima_iint_cache {
@@ -128,13 +126,11 @@ void ima_template_show(struct seq_file *m, void *e,
128 */ 126 */
129struct ima_iint_cache *ima_iint_insert(struct inode *inode); 127struct ima_iint_cache *ima_iint_insert(struct inode *inode);
130struct ima_iint_cache *ima_iint_find_get(struct inode *inode); 128struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
131struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
132void ima_iint_delete(struct inode *inode);
133void iint_free(struct kref *kref); 129void iint_free(struct kref *kref);
134void iint_rcu_free(struct rcu_head *rcu); 130void iint_rcu_free(struct rcu_head *rcu);
135 131
136/* IMA policy related functions */ 132/* IMA policy related functions */
137enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; 133enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
138 134
139int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); 135int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
140void ima_init_policy(void); 136void ima_init_policy(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 3cd58b60afd2..52015d098fdf 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -13,6 +13,7 @@
13 * and store_template. 13 * and store_template.
14 */ 14 */
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h>
16 17
17#include "ima.h" 18#include "ima.h"
18static const char *IMA_TEMPLATE_NAME = "ima"; 19static const char *IMA_TEMPLATE_NAME = "ima";
@@ -95,12 +96,12 @@ err_out:
95 * ima_must_measure - measure decision based on policy. 96 * ima_must_measure - measure decision based on policy.
96 * @inode: pointer to inode to measure 97 * @inode: pointer to inode to measure
97 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) 98 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
98 * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP) 99 * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP)
99 * 100 *
100 * The policy is defined in terms of keypairs: 101 * The policy is defined in terms of keypairs:
101 * subj=, obj=, type=, func=, mask=, fsmagic= 102 * subj=, obj=, type=, func=, mask=, fsmagic=
102 * subj,obj, and type: are LSM specific. 103 * subj,obj, and type: are LSM specific.
103 * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP 104 * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP
104 * mask: contains the permission mask 105 * mask: contains the permission mask
105 * fsmagic: hex value 106 * fsmagic: hex value
106 * 107 *
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index ff513ff737f5..5af76340470c 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/gfp.h>
14#include <linux/audit.h> 15#include <linux/audit.h>
15#include "ima.h" 16#include "ima.h"
16 17
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 46642a19bc78..952e51373f58 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -18,6 +18,7 @@
18#include <linux/crypto.h> 18#include <linux/crypto.h>
19#include <linux/scatterlist.h> 19#include <linux/scatterlist.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/slab.h>
21#include "ima.h" 22#include "ima.h"
22 23
23static int init_desc(struct hash_desc *desc) 24static int init_desc(struct hash_desc *desc)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 0c72c9c38956..07cb9c338cc4 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -16,6 +16,7 @@
16 * current measurement list and IMA statistics 16 * current measurement list and IMA statistics
17 */ 17 */
18#include <linux/fcntl.h> 18#include <linux/fcntl.h>
19#include <linux/slab.h>
19#include <linux/module.h> 20#include <linux/module.h>
20#include <linux/seq_file.h> 21#include <linux/seq_file.h>
21#include <linux/rculist.h> 22#include <linux/rculist.h>
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index a4e2b1dac943..2c744d488014 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -14,13 +14,12 @@
14 * - cache integrity information associated with an inode 14 * - cache integrity information associated with an inode
15 * using a radix tree. 15 * using a radix tree.
16 */ 16 */
17#include <linux/slab.h>
17#include <linux/module.h> 18#include <linux/module.h>
18#include <linux/spinlock.h> 19#include <linux/spinlock.h>
19#include <linux/radix-tree.h> 20#include <linux/radix-tree.h>
20#include "ima.h" 21#include "ima.h"
21 22
22#define ima_iint_delete ima_inode_free
23
24RADIX_TREE(ima_iint_store, GFP_ATOMIC); 23RADIX_TREE(ima_iint_store, GFP_ATOMIC);
25DEFINE_SPINLOCK(ima_iint_lock); 24DEFINE_SPINLOCK(ima_iint_lock);
26 25
@@ -45,22 +44,18 @@ out:
45 return iint; 44 return iint;
46} 45}
47 46
48/* Allocate memory for the iint associated with the inode 47/**
49 * from the iint_cache slab, initialize the iint, and 48 * ima_inode_alloc - allocate an iint associated with an inode
50 * insert it into the radix tree. 49 * @inode: pointer to the inode
51 *
52 * On success return a pointer to the iint; on failure return NULL.
53 */ 50 */
54struct ima_iint_cache *ima_iint_insert(struct inode *inode) 51int ima_inode_alloc(struct inode *inode)
55{ 52{
56 struct ima_iint_cache *iint = NULL; 53 struct ima_iint_cache *iint = NULL;
57 int rc = 0; 54 int rc = 0;
58 55
59 if (!ima_initialized)
60 return iint;
61 iint = kmem_cache_alloc(iint_cache, GFP_NOFS); 56 iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
62 if (!iint) 57 if (!iint)
63 return iint; 58 return -ENOMEM;
64 59
65 rc = radix_tree_preload(GFP_NOFS); 60 rc = radix_tree_preload(GFP_NOFS);
66 if (rc < 0) 61 if (rc < 0)
@@ -69,67 +64,14 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode)
69 spin_lock(&ima_iint_lock); 64 spin_lock(&ima_iint_lock);
70 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); 65 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
71 spin_unlock(&ima_iint_lock); 66 spin_unlock(&ima_iint_lock);
67 radix_tree_preload_end();
72out: 68out:
73 if (rc < 0) { 69 if (rc < 0)
74 kmem_cache_free(iint_cache, iint); 70 kmem_cache_free(iint_cache, iint);
75 if (rc == -EEXIST) {
76 spin_lock(&ima_iint_lock);
77 iint = radix_tree_lookup(&ima_iint_store,
78 (unsigned long)inode);
79 spin_unlock(&ima_iint_lock);
80 } else
81 iint = NULL;
82 }
83 radix_tree_preload_end();
84 return iint;
85}
86 71
87/** 72 return rc;
88 * ima_inode_alloc - allocate an iint associated with an inode
89 * @inode: pointer to the inode
90 *
91 * Return 0 on success, 1 on failure.
92 */
93int ima_inode_alloc(struct inode *inode)
94{
95 struct ima_iint_cache *iint;
96
97 if (!ima_initialized)
98 return 0;
99
100 iint = ima_iint_insert(inode);
101 if (!iint)
102 return 1;
103 return 0;
104} 73}
105 74
106/* ima_iint_find_insert_get - get the iint associated with an inode
107 *
108 * Most insertions are done at inode_alloc, except those allocated
109 * before late_initcall. When the iint does not exist, allocate it,
110 * initialize and insert it, and increment the iint refcount.
111 *
112 * (Can't initialize at security_initcall before any inodes are
113 * allocated, got to wait at least until proc_init.)
114 *
115 * Return the iint.
116 */
117struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
118{
119 struct ima_iint_cache *iint = NULL;
120
121 iint = ima_iint_find_get(inode);
122 if (iint)
123 return iint;
124
125 iint = ima_iint_insert(inode);
126 if (iint)
127 kref_get(&iint->refcount);
128
129 return iint;
130}
131EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
132
133/* iint_free - called when the iint refcount goes to zero */ 75/* iint_free - called when the iint refcount goes to zero */
134void iint_free(struct kref *kref) 76void iint_free(struct kref *kref)
135{ 77{
@@ -164,17 +106,15 @@ void iint_rcu_free(struct rcu_head *rcu_head)
164} 106}
165 107
166/** 108/**
167 * ima_iint_delete - called on integrity_inode_free 109 * ima_inode_free - called on security_inode_free
168 * @inode: pointer to the inode 110 * @inode: pointer to the inode
169 * 111 *
170 * Free the integrity information(iint) associated with an inode. 112 * Free the integrity information(iint) associated with an inode.
171 */ 113 */
172void ima_iint_delete(struct inode *inode) 114void ima_inode_free(struct inode *inode)
173{ 115{
174 struct ima_iint_cache *iint; 116 struct ima_iint_cache *iint;
175 117
176 if (!ima_initialized)
177 return;
178 spin_lock(&ima_iint_lock); 118 spin_lock(&ima_iint_lock);
179 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); 119 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
180 spin_unlock(&ima_iint_lock); 120 spin_unlock(&ima_iint_lock);
@@ -196,9 +136,11 @@ static void init_once(void *foo)
196 kref_set(&iint->refcount, 1); 136 kref_set(&iint->refcount, 1);
197} 137}
198 138
199void __init ima_iintcache_init(void) 139static int __init ima_iintcache_init(void)
200{ 140{
201 iint_cache = 141 iint_cache =
202 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, 142 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
203 SLAB_PANIC, init_once); 143 SLAB_PANIC, init_once);
144 return 0;
204} 145}
146security_initcall(ima_iintcache_init);
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index a40da7ae5900..b1bcb702a27c 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -16,6 +16,7 @@
16 */ 16 */
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/scatterlist.h> 18#include <linux/scatterlist.h>
19#include <linux/slab.h>
19#include <linux/err.h> 20#include <linux/err.h>
20#include "ima.h" 21#include "ima.h"
21 22
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b85e61bcf246..b2c89d9de2a4 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -13,14 +13,15 @@
13 * License. 13 * License.
14 * 14 *
15 * File: ima_main.c 15 * File: ima_main.c
16 * implements the IMA hooks: ima_bprm_check, ima_file_mmap, 16 * implements the IMA hooks: ima_bprm_check, ima_file_mmap,
17 * and ima_path_check. 17 * and ima_file_check.
18 */ 18 */
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/file.h> 20#include <linux/file.h>
21#include <linux/binfmts.h> 21#include <linux/binfmts.h>
22#include <linux/mount.h> 22#include <linux/mount.h>
23#include <linux/mman.h> 23#include <linux/mman.h>
24#include <linux/slab.h>
24 25
25#include "ima.h" 26#include "ima.h"
26 27
@@ -35,50 +36,53 @@ static int __init hash_setup(char *str)
35} 36}
36__setup("ima_hash=", hash_setup); 37__setup("ima_hash=", hash_setup);
37 38
38/** 39struct ima_imbalance {
39 * ima_file_free - called on __fput() 40 struct hlist_node node;
40 * @file: pointer to file structure being freed 41 unsigned long fsmagic;
42};
43
44/*
45 * ima_limit_imbalance - emit one imbalance message per filesystem type
41 * 46 *
42 * Flag files that changed, based on i_version; 47 * Maintain list of filesystem types that do not measure files properly.
43 * and decrement the iint readcount/writecount. 48 * Return false if unknown, true if known.
44 */ 49 */
45void ima_file_free(struct file *file) 50static bool ima_limit_imbalance(struct file *file)
46{ 51{
47 struct inode *inode = file->f_dentry->d_inode; 52 static DEFINE_SPINLOCK(ima_imbalance_lock);
48 struct ima_iint_cache *iint; 53 static HLIST_HEAD(ima_imbalance_list);
49 54
50 if (!ima_initialized || !S_ISREG(inode->i_mode)) 55 struct super_block *sb = file->f_dentry->d_sb;
51 return; 56 struct ima_imbalance *entry;
52 iint = ima_iint_find_get(inode); 57 struct hlist_node *node;
53 if (!iint) 58 bool found = false;
54 return; 59
55 60 rcu_read_lock();
56 mutex_lock(&iint->mutex); 61 hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
57 if (iint->opencount <= 0) { 62 if (entry->fsmagic == sb->s_magic) {
58 printk(KERN_INFO 63 found = true;
59 "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n", 64 break;
60 __FUNCTION__, file->f_dentry->d_name.name,
61 iint->readcount, iint->writecount,
62 iint->opencount, atomic_long_read(&file->f_count));
63 if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
64 dump_stack();
65 iint->flags |= IMA_IINT_DUMP_STACK;
66 } 65 }
67 } 66 }
68 iint->opencount--; 67 rcu_read_unlock();
69 68 if (found)
70 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) 69 goto out;
71 iint->readcount--;
72 70
73 if (file->f_mode & FMODE_WRITE) { 71 entry = kmalloc(sizeof(*entry), GFP_NOFS);
74 iint->writecount--; 72 if (!entry)
75 if (iint->writecount == 0) { 73 goto out;
76 if (iint->version != inode->i_version) 74 entry->fsmagic = sb->s_magic;
77 iint->flags &= ~IMA_MEASURED; 75 spin_lock(&ima_imbalance_lock);
78 } 76 /*
79 } 77 * we could have raced and something else might have added this fs
80 mutex_unlock(&iint->mutex); 78 * to the list, but we don't really care
81 kref_put(&iint->refcount, iint_free); 79 */
80 hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
81 spin_unlock(&ima_imbalance_lock);
82 printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
83 entry->fsmagic);
84out:
85 return found;
82} 86}
83 87
84/* ima_read_write_check - reflect possible reading/writing errors in the PCR. 88/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
@@ -111,196 +115,142 @@ static void ima_read_write_check(enum iint_pcr_error error,
111 } 115 }
112} 116}
113 117
114static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, 118/*
115 const unsigned char *filename) 119 * Update the counts given an fmode_t
120 */
121static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
116{ 122{
117 int rc = 0; 123 BUG_ON(!mutex_is_locked(&iint->mutex));
118
119 iint->opencount++;
120 iint->readcount++;
121
122 rc = ima_collect_measurement(iint, file);
123 if (!rc)
124 ima_store_measurement(iint, file, filename);
125 return rc;
126}
127 124
128static void ima_update_counts(struct ima_iint_cache *iint, int mask)
129{
130 iint->opencount++; 125 iint->opencount++;
131 if ((mask & MAY_WRITE) || (mask == 0)) 126 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
132 iint->writecount++;
133 else if (mask & (MAY_READ | MAY_EXEC))
134 iint->readcount++; 127 iint->readcount++;
128 if (mode & FMODE_WRITE)
129 iint->writecount++;
135} 130}
136 131
137/** 132/*
138 * ima_path_check - based on policy, collect/store measurement. 133 * ima_counts_get - increment file counts
139 * @path: contains a pointer to the path to be measured
140 * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
141 *
142 * Measure the file being open for readonly, based on the
143 * ima_must_measure() policy decision.
144 * 134 *
145 * Keep read/write counters for all files, but only 135 * Maintain read/write counters for all files, but only
146 * invalidate the PCR for measured files: 136 * invalidate the PCR for measured files:
147 * - Opening a file for write when already open for read, 137 * - Opening a file for write when already open for read,
148 * results in a time of measure, time of use (ToMToU) error. 138 * results in a time of measure, time of use (ToMToU) error.
149 * - Opening a file for read when already open for write, 139 * - Opening a file for read when already open for write,
150 * could result in a file measurement error. 140 * could result in a file measurement error.
151 * 141 *
152 * Always return 0 and audit dentry_open failures.
153 * (Return code will be based upon measurement appraisal.)
154 */ 142 */
155int ima_path_check(struct path *path, int mask, int update_counts) 143void ima_counts_get(struct file *file)
156{ 144{
157 struct inode *inode = path->dentry->d_inode; 145 struct dentry *dentry = file->f_path.dentry;
146 struct inode *inode = dentry->d_inode;
147 fmode_t mode = file->f_mode;
158 struct ima_iint_cache *iint; 148 struct ima_iint_cache *iint;
159 struct file *file = NULL;
160 int rc; 149 int rc;
161 150
162 if (!ima_initialized || !S_ISREG(inode->i_mode)) 151 if (!ima_initialized || !S_ISREG(inode->i_mode))
163 return 0; 152 return;
164 iint = ima_iint_find_insert_get(inode); 153 iint = ima_iint_find_get(inode);
165 if (!iint) 154 if (!iint)
166 return 0; 155 return;
167
168 mutex_lock(&iint->mutex); 156 mutex_lock(&iint->mutex);
169 if (update_counts) 157 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
170 ima_update_counts(iint, mask);
171
172 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
173 if (rc < 0) 158 if (rc < 0)
174 goto out; 159 goto out;
175 160
176 if ((mask & MAY_WRITE) || (mask == 0)) 161 if (mode & FMODE_WRITE) {
177 ima_read_write_check(TOMTOU, iint, inode, 162 ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
178 path->dentry->d_name.name);
179
180 if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
181 goto out; 163 goto out;
182
183 ima_read_write_check(OPEN_WRITERS, iint, inode,
184 path->dentry->d_name.name);
185 if (!(iint->flags & IMA_MEASURED)) {
186 struct dentry *dentry = dget(path->dentry);
187 struct vfsmount *mnt = mntget(path->mnt);
188
189 file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
190 current_cred());
191 if (IS_ERR(file)) {
192 int audit_info = 0;
193
194 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
195 dentry->d_name.name,
196 "add_measurement",
197 "dentry_open failed",
198 1, audit_info);
199 file = NULL;
200 goto out;
201 }
202 rc = get_path_measurement(iint, file, dentry->d_name.name);
203 } 164 }
165 ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
204out: 166out:
167 ima_inc_counts(iint, file->f_mode);
205 mutex_unlock(&iint->mutex); 168 mutex_unlock(&iint->mutex);
206 if (file) 169
207 fput(file);
208 kref_put(&iint->refcount, iint_free); 170 kref_put(&iint->refcount, iint_free);
209 return 0;
210} 171}
211EXPORT_SYMBOL_GPL(ima_path_check);
212 172
213static int process_measurement(struct file *file, const unsigned char *filename, 173/*
214 int mask, int function) 174 * Decrement ima counts
175 */
176static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
177 struct file *file)
215{ 178{
216 struct inode *inode = file->f_dentry->d_inode; 179 mode_t mode = file->f_mode;
217 struct ima_iint_cache *iint; 180 BUG_ON(!mutex_is_locked(&iint->mutex));
218 int rc;
219 181
220 if (!ima_initialized || !S_ISREG(inode->i_mode)) 182 iint->opencount--;
221 return 0; 183 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
222 iint = ima_iint_find_insert_get(inode); 184 iint->readcount--;
223 if (!iint) 185 if (mode & FMODE_WRITE) {
224 return -ENOMEM; 186 iint->writecount--;
225 187 if (iint->writecount == 0) {
226 mutex_lock(&iint->mutex); 188 if (iint->version != inode->i_version)
227 rc = ima_must_measure(iint, inode, mask, function); 189 iint->flags &= ~IMA_MEASURED;
228 if (rc != 0) 190 }
229 goto out; 191 }
230 192
231 rc = ima_collect_measurement(iint, file); 193 if (((iint->opencount < 0) ||
232 if (!rc) 194 (iint->readcount < 0) ||
233 ima_store_measurement(iint, file, filename); 195 (iint->writecount < 0)) &&
234out: 196 !ima_limit_imbalance(file)) {
235 mutex_unlock(&iint->mutex); 197 printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
236 kref_put(&iint->refcount, iint_free); 198 __FUNCTION__, iint->readcount, iint->writecount,
237 return rc; 199 iint->opencount);
200 dump_stack();
201 }
238} 202}
239 203
240/* 204/**
241 * ima_counts_put - decrement file counts 205 * ima_file_free - called on __fput()
206 * @file: pointer to file structure being freed
242 * 207 *
243 * File counts are incremented in ima_path_check. On file open 208 * Flag files that changed, based on i_version;
244 * error, such as ETXTBSY, decrement the counts to prevent 209 * and decrement the iint readcount/writecount.
245 * unnecessary imbalance messages.
246 */ 210 */
247void ima_counts_put(struct path *path, int mask) 211void ima_file_free(struct file *file)
248{ 212{
249 struct inode *inode = path->dentry->d_inode; 213 struct inode *inode = file->f_dentry->d_inode;
250 struct ima_iint_cache *iint; 214 struct ima_iint_cache *iint;
251 215
252 /* The inode may already have been freed, freeing the iint 216 if (!ima_initialized || !S_ISREG(inode->i_mode))
253 * with it. Verify the inode is not NULL before dereferencing
254 * it.
255 */
256 if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
257 return; 217 return;
258 iint = ima_iint_find_insert_get(inode); 218 iint = ima_iint_find_get(inode);
259 if (!iint) 219 if (!iint)
260 return; 220 return;
261 221
262 mutex_lock(&iint->mutex); 222 mutex_lock(&iint->mutex);
263 iint->opencount--; 223 ima_dec_counts(iint, inode, file);
264 if ((mask & MAY_WRITE) || (mask == 0))
265 iint->writecount--;
266 else if (mask & (MAY_READ | MAY_EXEC))
267 iint->readcount--;
268 mutex_unlock(&iint->mutex); 224 mutex_unlock(&iint->mutex);
269
270 kref_put(&iint->refcount, iint_free); 225 kref_put(&iint->refcount, iint_free);
271} 226}
272 227
273/* 228static int process_measurement(struct file *file, const unsigned char *filename,
274 * ima_counts_get - increment file counts 229 int mask, int function)
275 *
276 * - for IPC shm and shmat file.
277 * - for nfsd exported files.
278 *
279 * Increment the counts for these files to prevent unnecessary
280 * imbalance messages.
281 */
282void ima_counts_get(struct file *file)
283{ 230{
284 struct inode *inode = file->f_dentry->d_inode; 231 struct inode *inode = file->f_dentry->d_inode;
285 struct ima_iint_cache *iint; 232 struct ima_iint_cache *iint;
233 int rc;
286 234
287 if (!ima_initialized || !S_ISREG(inode->i_mode)) 235 if (!ima_initialized || !S_ISREG(inode->i_mode))
288 return; 236 return 0;
289 iint = ima_iint_find_insert_get(inode); 237 iint = ima_iint_find_get(inode);
290 if (!iint) 238 if (!iint)
291 return; 239 return -ENOMEM;
240
292 mutex_lock(&iint->mutex); 241 mutex_lock(&iint->mutex);
293 iint->opencount++; 242 rc = ima_must_measure(iint, inode, mask, function);
294 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) 243 if (rc != 0)
295 iint->readcount++; 244 goto out;
296 245
297 if (file->f_mode & FMODE_WRITE) 246 rc = ima_collect_measurement(iint, file);
298 iint->writecount++; 247 if (!rc)
248 ima_store_measurement(iint, file, filename);
249out:
299 mutex_unlock(&iint->mutex); 250 mutex_unlock(&iint->mutex);
300
301 kref_put(&iint->refcount, iint_free); 251 kref_put(&iint->refcount, iint_free);
252 return rc;
302} 253}
303EXPORT_SYMBOL_GPL(ima_counts_get);
304 254
305/** 255/**
306 * ima_file_mmap - based on policy, collect/store measurement. 256 * ima_file_mmap - based on policy, collect/store measurement.
@@ -347,11 +297,31 @@ int ima_bprm_check(struct linux_binprm *bprm)
347 return 0; 297 return 0;
348} 298}
349 299
300/**
301 * ima_path_check - based on policy, collect/store measurement.
302 * @file: pointer to the file to be measured
303 * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
304 *
305 * Measure files based on the ima_must_measure() policy decision.
306 *
307 * Always return 0 and audit dentry_open failures.
308 * (Return code will be based upon measurement appraisal.)
309 */
310int ima_file_check(struct file *file, int mask)
311{
312 int rc;
313
314 rc = process_measurement(file, file->f_dentry->d_name.name,
315 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
316 FILE_CHECK);
317 return 0;
318}
319EXPORT_SYMBOL_GPL(ima_file_check);
320
350static int __init init_ima(void) 321static int __init init_ima(void)
351{ 322{
352 int error; 323 int error;
353 324
354 ima_iintcache_init();
355 error = ima_init(); 325 error = ima_init();
356 ima_initialized = 1; 326 ima_initialized = 1;
357 return error; 327 return error;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index e1278399b345..8643a93c5963 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -15,6 +15,7 @@
15#include <linux/security.h> 15#include <linux/security.h>
16#include <linux/magic.h> 16#include <linux/magic.h>
17#include <linux/parser.h> 17#include <linux/parser.h>
18#include <linux/slab.h>
18 19
19#include "ima.h" 20#include "ima.h"
20 21
@@ -67,7 +68,7 @@ static struct ima_measure_rule_entry default_rules[] = {
67 .flags = IMA_FUNC | IMA_MASK}, 68 .flags = IMA_FUNC | IMA_MASK},
68 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, 69 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
69 .flags = IMA_FUNC | IMA_MASK}, 70 .flags = IMA_FUNC | IMA_MASK},
70 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, 71 {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0,
71 .flags = IMA_FUNC | IMA_MASK | IMA_UID}, 72 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
72}; 73};
73 74
@@ -282,8 +283,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
282 break; 283 break;
283 case Opt_func: 284 case Opt_func:
284 audit_log_format(ab, "func=%s ", args[0].from); 285 audit_log_format(ab, "func=%s ", args[0].from);
285 if (strcmp(args[0].from, "PATH_CHECK") == 0) 286 if (strcmp(args[0].from, "FILE_CHECK") == 0)
286 entry->func = PATH_CHECK; 287 entry->func = FILE_CHECK;
288 /* PATH_CHECK is for backwards compat */
289 else if (strcmp(args[0].from, "PATH_CHECK") == 0)
290 entry->func = FILE_CHECK;
287 else if (strcmp(args[0].from, "FILE_MMAP") == 0) 291 else if (strcmp(args[0].from, "FILE_MMAP") == 0)
288 entry->func = FILE_MMAP; 292 entry->func = FILE_MMAP;
289 else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 293 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index a0880e9c8e05..46ba62b1adf5 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -20,6 +20,7 @@
20 */ 20 */
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/rculist.h> 22#include <linux/rculist.h>
23#include <linux/slab.h>
23#include "ima.h" 24#include "ima.h"
24 25
25LIST_HEAD(ima_measurements); /* list of all measurements */ 26LIST_HEAD(ima_measurements); /* list of all measurements */