aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r--security/integrity/ima/ima_main.c57
1 files changed, 23 insertions, 34 deletions
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}