aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-25 14:41:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-26 14:37:18 -0400
commitad16ad00c34d3f320a5876b3d711ef6bc81362e1 (patch)
tree7cf3b755567fde2850d2ea7f4a186a0dcea6b80f /security
parent15aac676778f206b42c4d7782b08f89246680485 (diff)
IMA: use inode->i_lock to protect read and write counters
Currently IMA used the iint->mutex to protect the i_readcount and i_writecount. This patch uses the inode->i_lock since we are going to start using in inode objects and that is the most appropriate lock. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima.h1
-rw-r--r--security/integrity/ima/ima_main.c57
2 files changed, 24 insertions, 34 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index f7af0110bcde..80aca3d2cb71 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -106,6 +106,7 @@ struct ima_iint_cache {
106 unsigned char flags; 106 unsigned char flags;
107 u8 digest[IMA_DIGEST_SIZE]; 107 u8 digest[IMA_DIGEST_SIZE];
108 struct mutex mutex; /* protects: version, flags, digest */ 108 struct mutex mutex; /* protects: version, flags, digest */
109 /* protected by inode->i_lock */
109 unsigned int readcount; /* measured files readcount */ 110 unsigned int readcount; /* measured files readcount */
110 unsigned int writecount;/* measured files writecount */ 111 unsigned int writecount;/* measured files writecount */
111 struct kref refcount; /* ima_iint_cache reference count */ 112 struct kref refcount; /* ima_iint_cache reference count */
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5a1bf3df11f8..2f9b5d50424e 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -85,42 +85,12 @@ out:
85 return found; 85 return found;
86} 86}
87 87
88/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
89 *
90 * When opening a file for read, if the file is already open for write,
91 * the file could change, resulting in a file measurement error.
92 *
93 * Opening a file for write, if the file is already open for read, results
94 * in a time of measure, time of use (ToMToU) error.
95 *
96 * In either case invalidate the PCR.
97 */
98enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
99static void ima_read_write_check(enum iint_pcr_error error,
100 struct ima_iint_cache *iint,
101 struct inode *inode,
102 const unsigned char *filename)
103{
104 switch (error) {
105 case TOMTOU:
106 if (iint->readcount > 0)
107 ima_add_violation(inode, filename, "invalid_pcr",
108 "ToMToU");
109 break;
110 case OPEN_WRITERS:
111 if (iint->writecount > 0)
112 ima_add_violation(inode, filename, "invalid_pcr",
113 "open_writers");
114 break;
115 }
116}
117
118/* 88/*
119 * Update the counts given an fmode_t 89 * Update the counts given an fmode_t
120 */ 90 */
121static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode) 91static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
122{ 92{
123 BUG_ON(!mutex_is_locked(&iint->mutex)); 93 assert_spin_locked(&iint->inode->i_lock);
124 94
125 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) 95 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
126 iint->readcount++; 96 iint->readcount++;
@@ -146,6 +116,7 @@ void ima_counts_get(struct file *file)
146 fmode_t mode = file->f_mode; 116 fmode_t mode = file->f_mode;
147 struct ima_iint_cache *iint; 117 struct ima_iint_cache *iint;
148 int rc; 118 int rc;
119 bool send_tomtou = false, send_writers = false;
149 120
150 if (!iint_initialized || !S_ISREG(inode->i_mode)) 121 if (!iint_initialized || !S_ISREG(inode->i_mode))
151 return; 122 return;
@@ -153,22 +124,35 @@ void ima_counts_get(struct file *file)
153 if (!iint) 124 if (!iint)
154 return; 125 return;
155 mutex_lock(&iint->mutex); 126 mutex_lock(&iint->mutex);
127 spin_lock(&inode->i_lock);
128
156 if (!ima_initialized) 129 if (!ima_initialized)
157 goto out; 130 goto out;
131
158 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); 132 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
159 if (rc < 0) 133 if (rc < 0)
160 goto out; 134 goto out;
161 135
162 if (mode & FMODE_WRITE) { 136 if (mode & FMODE_WRITE) {
163 ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name); 137 if (iint->readcount)
138 send_tomtou = true;
164 goto out; 139 goto out;
165 } 140 }
166 ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name); 141
142 if (atomic_read(&inode->i_writecount) > 0)
143 send_writers = true;
167out: 144out:
168 ima_inc_counts(iint, file->f_mode); 145 ima_inc_counts(iint, file->f_mode);
146 spin_unlock(&inode->i_lock);
169 mutex_unlock(&iint->mutex); 147 mutex_unlock(&iint->mutex);
170
171 kref_put(&iint->refcount, iint_free); 148 kref_put(&iint->refcount, iint_free);
149
150 if (send_tomtou)
151 ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
152 "ToMToU");
153 if (send_writers)
154 ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
155 "open_writers");
172} 156}
173 157
174/* 158/*
@@ -181,6 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
181 bool dump = false; 165 bool dump = false;
182 166
183 BUG_ON(!mutex_is_locked(&iint->mutex)); 167 BUG_ON(!mutex_is_locked(&iint->mutex));
168 assert_spin_locked(&inode->i_lock);
184 169
185 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { 170 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
186 if (unlikely(iint->readcount == 0)) 171 if (unlikely(iint->readcount == 0))
@@ -223,7 +208,11 @@ void ima_file_free(struct file *file)
223 return; 208 return;
224 209
225 mutex_lock(&iint->mutex); 210 mutex_lock(&iint->mutex);
211 spin_lock(&inode->i_lock);
212
226 ima_dec_counts(iint, inode, file); 213 ima_dec_counts(iint, inode, file);
214
215 spin_unlock(&inode->i_lock);
227 mutex_unlock(&iint->mutex); 216 mutex_unlock(&iint->mutex);
228 kref_put(&iint->refcount, iint_free); 217 kref_put(&iint->refcount, iint_free);
229} 218}