aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/inode.c1
-rw-r--r--include/linux/fs.h4
-rw-r--r--security/integrity/ima/ima.h3
-rw-r--r--security/integrity/ima/ima_api.c2
-rw-r--r--security/integrity/ima/ima_iint.c11
-rw-r--r--security/integrity/ima/ima_main.c35
6 files changed, 22 insertions, 34 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 86464332e590..56d909d69bc8 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -24,6 +24,7 @@
24#include <linux/mount.h> 24#include <linux/mount.h>
25#include <linux/async.h> 25#include <linux/async.h>
26#include <linux/posix_acl.h> 26#include <linux/posix_acl.h>
27#include <linux/ima.h>
27 28
28/* 29/*
29 * This is needed for the following functions: 30 * This is needed for the following functions:
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 63d069bd80b7..01e3a0047fed 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -776,6 +776,10 @@ struct inode {
776 776
777 unsigned int i_flags; 777 unsigned int i_flags;
778 778
779#ifdef CONFIG_IMA
780 /* protected by i_lock */
781 unsigned int i_readcount; /* struct files open RO */
782#endif
779 atomic_t i_writecount; 783 atomic_t i_writecount;
780#ifdef CONFIG_SECURITY 784#ifdef CONFIG_SECURITY
781 void *i_security; 785 void *i_security;
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b546b90f5fa8..27849e1656dc 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -70,6 +70,7 @@ int ima_init(void);
70void ima_cleanup(void); 70void ima_cleanup(void);
71int ima_fs_init(void); 71int ima_fs_init(void);
72void ima_fs_cleanup(void); 72void ima_fs_cleanup(void);
73int ima_inode_alloc(struct inode *inode);
73int ima_add_template_entry(struct ima_template_entry *entry, int violation, 74int ima_add_template_entry(struct ima_template_entry *entry, int violation,
74 const char *op, struct inode *inode); 75 const char *op, struct inode *inode);
75int ima_calc_hash(struct file *file, char *digest); 76int ima_calc_hash(struct file *file, char *digest);
@@ -106,8 +107,6 @@ struct ima_iint_cache {
106 unsigned char flags; 107 unsigned char flags;
107 u8 digest[IMA_DIGEST_SIZE]; 108 u8 digest[IMA_DIGEST_SIZE];
108 struct mutex mutex; /* protects: version, flags, digest */ 109 struct mutex mutex; /* protects: version, flags, digest */
109 /* protected by inode->i_lock */
110 unsigned int readcount; /* measured files readcount */
111 struct kref refcount; /* ima_iint_cache reference count */ 110 struct kref refcount; /* ima_iint_cache reference count */
112}; 111};
113 112
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 52015d098fdf..d3963de6003d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -116,7 +116,7 @@ int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
116{ 116{
117 int must_measure; 117 int must_measure;
118 118
119 if (iint->flags & IMA_MEASURED) 119 if (iint && iint->flags & IMA_MEASURED)
120 return 1; 120 return 1;
121 121
122 must_measure = ima_match_policy(inode, function, mask); 122 must_measure = ima_match_policy(inode, function, mask);
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index e68891f8d55a..0936a7197e47 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -124,11 +124,6 @@ void iint_free(struct kref *kref)
124 refcount); 124 refcount);
125 iint->version = 0; 125 iint->version = 0;
126 iint->flags = 0UL; 126 iint->flags = 0UL;
127 if (iint->readcount != 0) {
128 printk(KERN_INFO "%s: readcount: %u\n", __func__,
129 iint->readcount);
130 iint->readcount = 0;
131 }
132 kref_init(&iint->refcount); 127 kref_init(&iint->refcount);
133 kmem_cache_free(iint_cache, iint); 128 kmem_cache_free(iint_cache, iint);
134} 129}
@@ -143,6 +138,11 @@ void ima_inode_free(struct inode *inode)
143{ 138{
144 struct ima_iint_cache *iint; 139 struct ima_iint_cache *iint;
145 140
141 if (inode->i_readcount)
142 printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
143
144 inode->i_readcount = 0;
145
146 spin_lock(&ima_iint_lock); 146 spin_lock(&ima_iint_lock);
147 iint = __ima_iint_find(inode); 147 iint = __ima_iint_find(inode);
148 if (iint) 148 if (iint)
@@ -160,7 +160,6 @@ static void init_once(void *foo)
160 iint->version = 0; 160 iint->version = 0;
161 iint->flags = 0UL; 161 iint->flags = 0UL;
162 mutex_init(&iint->mutex); 162 mutex_init(&iint->mutex);
163 iint->readcount = 0;
164 kref_init(&iint->refcount); 163 kref_init(&iint->refcount);
165} 164}
166 165
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 24660bf3f82a..2a77b14fee27 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -86,17 +86,6 @@ out:
86} 86}
87 87
88/* 88/*
89 * Update the counts given an fmode_t
90 */
91static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
92{
93 assert_spin_locked(&iint->inode->i_lock);
94
95 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
96 iint->readcount++;
97}
98
99/*
100 * ima_counts_get - increment file counts 89 * ima_counts_get - increment file counts
101 * 90 *
102 * Maintain read/write counters for all files, but only 91 * Maintain read/write counters for all files, but only
@@ -112,27 +101,23 @@ void ima_counts_get(struct file *file)
112 struct dentry *dentry = file->f_path.dentry; 101 struct dentry *dentry = file->f_path.dentry;
113 struct inode *inode = dentry->d_inode; 102 struct inode *inode = dentry->d_inode;
114 fmode_t mode = file->f_mode; 103 fmode_t mode = file->f_mode;
115 struct ima_iint_cache *iint;
116 int rc; 104 int rc;
117 bool send_tomtou = false, send_writers = false; 105 bool send_tomtou = false, send_writers = false;
118 106
119 if (!iint_initialized || !S_ISREG(inode->i_mode)) 107 if (!S_ISREG(inode->i_mode))
120 return; 108 return;
121 iint = ima_iint_find_get(inode); 109
122 if (!iint)
123 return;
124 mutex_lock(&iint->mutex);
125 spin_lock(&inode->i_lock); 110 spin_lock(&inode->i_lock);
126 111
127 if (!ima_initialized) 112 if (!ima_initialized)
128 goto out; 113 goto out;
129 114
130 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); 115 rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
131 if (rc < 0) 116 if (rc < 0)
132 goto out; 117 goto out;
133 118
134 if (mode & FMODE_WRITE) { 119 if (mode & FMODE_WRITE) {
135 if (iint->readcount) 120 if (inode->i_readcount)
136 send_tomtou = true; 121 send_tomtou = true;
137 goto out; 122 goto out;
138 } 123 }
@@ -140,10 +125,10 @@ void ima_counts_get(struct file *file)
140 if (atomic_read(&inode->i_writecount) > 0) 125 if (atomic_read(&inode->i_writecount) > 0)
141 send_writers = true; 126 send_writers = true;
142out: 127out:
143 ima_inc_counts(iint, file->f_mode); 128 /* remember the vfs deals with i_writecount */
129 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
130 inode->i_readcount++;
144 spin_unlock(&inode->i_lock); 131 spin_unlock(&inode->i_lock);
145 mutex_unlock(&iint->mutex);
146 kref_put(&iint->refcount, iint_free);
147 132
148 if (send_tomtou) 133 if (send_tomtou)
149 ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", 134 ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
@@ -166,9 +151,9 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
166 assert_spin_locked(&inode->i_lock); 151 assert_spin_locked(&inode->i_lock);
167 152
168 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 153 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
169 if (unlikely(iint->readcount == 0)) 154 if (unlikely(inode->i_readcount == 0))
170 dump = true; 155 dump = true;
171 iint->readcount--; 156 inode->i_readcount--;
172 } 157 }
173 if (mode & FMODE_WRITE) { 158 if (mode & FMODE_WRITE) {
174 if (atomic_read(&inode->i_writecount) <= 0) 159 if (atomic_read(&inode->i_writecount) <= 0)
@@ -180,7 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
180 165
181 if (dump && !ima_limit_imbalance(file)) { 166 if (dump && !ima_limit_imbalance(file)) {
182 printk(KERN_INFO "%s: open/free imbalance (r:%u)\n", 167 printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
183 __func__, iint->readcount); 168 __func__, inode->i_readcount);
184 dump_stack(); 169 dump_stack();
185 } 170 }
186} 171}