diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r-- | security/integrity/ima/ima_main.c | 138 |
1 files changed, 63 insertions, 75 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index dba965de90d3..5127afcc4b89 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -61,7 +61,8 @@ static void ima_rdwr_violation_check(struct file *file) | |||
61 | fmode_t mode = file->f_mode; | 61 | fmode_t mode = file->f_mode; |
62 | int must_measure; | 62 | int must_measure; |
63 | bool send_tomtou = false, send_writers = false; | 63 | bool send_tomtou = false, send_writers = false; |
64 | unsigned char *pathname = NULL, *pathbuf = NULL; | 64 | char *pathbuf = NULL; |
65 | const char *pathname; | ||
65 | 66 | ||
66 | if (!S_ISREG(inode->i_mode) || !ima_initialized) | 67 | if (!S_ISREG(inode->i_mode) || !ima_initialized) |
67 | return; | 68 | return; |
@@ -86,22 +87,15 @@ out: | |||
86 | if (!send_tomtou && !send_writers) | 87 | if (!send_tomtou && !send_writers) |
87 | return; | 88 | return; |
88 | 89 | ||
89 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 90 | pathname = ima_d_path(&file->f_path, &pathbuf); |
90 | pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | 91 | if (!pathname || strlen(pathname) > IMA_EVENT_NAME_LEN_MAX) |
91 | if (pathbuf) { | 92 | pathname = dentry->d_name.name; |
92 | pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11); | 93 | |
93 | if (IS_ERR(pathname)) | ||
94 | pathname = NULL; | ||
95 | else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX) | ||
96 | pathname = NULL; | ||
97 | } | ||
98 | if (send_tomtou) | 94 | if (send_tomtou) |
99 | ima_add_violation(inode, | 95 | ima_add_violation(inode, pathname, |
100 | !pathname ? dentry->d_name.name : pathname, | ||
101 | "invalid_pcr", "ToMToU"); | 96 | "invalid_pcr", "ToMToU"); |
102 | if (send_writers) | 97 | if (send_writers) |
103 | ima_add_violation(inode, | 98 | ima_add_violation(inode, pathname, |
104 | !pathname ? dentry->d_name.name : pathname, | ||
105 | "invalid_pcr", "open_writers"); | 99 | "invalid_pcr", "open_writers"); |
106 | kfree(pathbuf); | 100 | kfree(pathbuf); |
107 | } | 101 | } |
@@ -145,25 +139,31 @@ void ima_file_free(struct file *file) | |||
145 | ima_check_last_writer(iint, inode, file); | 139 | ima_check_last_writer(iint, inode, file); |
146 | } | 140 | } |
147 | 141 | ||
148 | static int process_measurement(struct file *file, const unsigned char *filename, | 142 | static int process_measurement(struct file *file, const char *filename, |
149 | int mask, int function) | 143 | int mask, int function) |
150 | { | 144 | { |
151 | struct inode *inode = file->f_dentry->d_inode; | 145 | struct inode *inode = file->f_dentry->d_inode; |
152 | struct integrity_iint_cache *iint; | 146 | struct integrity_iint_cache *iint; |
153 | unsigned char *pathname = NULL, *pathbuf = NULL; | 147 | char *pathbuf = NULL; |
154 | int rc = -ENOMEM, action, must_appraise; | 148 | const char *pathname = NULL; |
149 | int rc = -ENOMEM, action, must_appraise, _func; | ||
155 | 150 | ||
156 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 151 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
157 | return 0; | 152 | return 0; |
158 | 153 | ||
159 | /* Determine if in appraise/audit/measurement policy, | 154 | /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action |
160 | * returns IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT bitmask. */ | 155 | * bitmask based on the appraise/audit/measurement policy. |
156 | * Included is the appraise submask. | ||
157 | */ | ||
161 | action = ima_get_action(inode, mask, function); | 158 | action = ima_get_action(inode, mask, function); |
162 | if (!action) | 159 | if (!action) |
163 | return 0; | 160 | return 0; |
164 | 161 | ||
165 | must_appraise = action & IMA_APPRAISE; | 162 | must_appraise = action & IMA_APPRAISE; |
166 | 163 | ||
164 | /* Is the appraise rule hook specific? */ | ||
165 | _func = (action & IMA_FILE_APPRAISE) ? FILE_CHECK : function; | ||
166 | |||
167 | mutex_lock(&inode->i_mutex); | 167 | mutex_lock(&inode->i_mutex); |
168 | 168 | ||
169 | iint = integrity_inode_get(inode); | 169 | iint = integrity_inode_get(inode); |
@@ -171,44 +171,45 @@ static int process_measurement(struct file *file, const unsigned char *filename, | |||
171 | goto out; | 171 | goto out; |
172 | 172 | ||
173 | /* Determine if already appraised/measured based on bitmask | 173 | /* Determine if already appraised/measured based on bitmask |
174 | * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED, | 174 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, |
175 | * IMA_AUDIT, IMA_AUDITED) */ | 175 | * IMA_AUDIT, IMA_AUDITED) |
176 | */ | ||
176 | iint->flags |= action; | 177 | iint->flags |= action; |
178 | action &= IMA_DO_MASK; | ||
177 | action &= ~((iint->flags & IMA_DONE_MASK) >> 1); | 179 | action &= ~((iint->flags & IMA_DONE_MASK) >> 1); |
178 | 180 | ||
179 | /* Nothing to do, just return existing appraised status */ | 181 | /* Nothing to do, just return existing appraised status */ |
180 | if (!action) { | 182 | if (!action) { |
181 | if (iint->flags & IMA_APPRAISED) | 183 | if (must_appraise) |
182 | rc = iint->ima_status; | 184 | rc = ima_get_cache_status(iint, _func); |
183 | goto out; | 185 | goto out_digsig; |
184 | } | 186 | } |
185 | 187 | ||
186 | rc = ima_collect_measurement(iint, file); | 188 | rc = ima_collect_measurement(iint, file); |
187 | if (rc != 0) | 189 | if (rc != 0) |
188 | goto out; | 190 | goto out_digsig; |
191 | |||
192 | if (function != BPRM_CHECK) | ||
193 | pathname = ima_d_path(&file->f_path, &pathbuf); | ||
194 | |||
195 | if (!pathname) | ||
196 | pathname = filename; | ||
189 | 197 | ||
190 | if (function != BPRM_CHECK) { | ||
191 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | ||
192 | pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL); | ||
193 | if (pathbuf) { | ||
194 | pathname = | ||
195 | d_path(&file->f_path, pathbuf, PATH_MAX + 11); | ||
196 | if (IS_ERR(pathname)) | ||
197 | pathname = NULL; | ||
198 | } | ||
199 | } | ||
200 | if (action & IMA_MEASURE) | 198 | if (action & IMA_MEASURE) |
201 | ima_store_measurement(iint, file, | 199 | ima_store_measurement(iint, file, pathname); |
202 | !pathname ? filename : pathname); | 200 | if (action & IMA_APPRAISE_SUBMASK) |
203 | if (action & IMA_APPRAISE) | 201 | rc = ima_appraise_measurement(_func, iint, file, pathname); |
204 | rc = ima_appraise_measurement(iint, file, | ||
205 | !pathname ? filename : pathname); | ||
206 | if (action & IMA_AUDIT) | 202 | if (action & IMA_AUDIT) |
207 | ima_audit_measurement(iint, !pathname ? filename : pathname); | 203 | ima_audit_measurement(iint, pathname); |
208 | kfree(pathbuf); | 204 | kfree(pathbuf); |
205 | out_digsig: | ||
206 | if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) | ||
207 | rc = -EACCES; | ||
209 | out: | 208 | out: |
210 | mutex_unlock(&inode->i_mutex); | 209 | mutex_unlock(&inode->i_mutex); |
211 | return (rc && must_appraise) ? -EACCES : 0; | 210 | if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) |
211 | return -EACCES; | ||
212 | return 0; | ||
212 | } | 213 | } |
213 | 214 | ||
214 | /** | 215 | /** |
@@ -219,19 +220,15 @@ out: | |||
219 | * Measure files being mmapped executable based on the ima_must_measure() | 220 | * Measure files being mmapped executable based on the ima_must_measure() |
220 | * policy decision. | 221 | * policy decision. |
221 | * | 222 | * |
222 | * Return 0 on success, an error code on failure. | 223 | * On success return 0. On integrity appraisal error, assuming the file |
223 | * (Based on the results of appraise_measurement().) | 224 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
224 | */ | 225 | */ |
225 | int ima_file_mmap(struct file *file, unsigned long prot) | 226 | int ima_file_mmap(struct file *file, unsigned long prot) |
226 | { | 227 | { |
227 | int rc = 0; | 228 | if (file && (prot & PROT_EXEC)) |
228 | 229 | return process_measurement(file, file->f_dentry->d_name.name, | |
229 | if (!file) | 230 | MAY_EXEC, MMAP_CHECK); |
230 | return 0; | 231 | return 0; |
231 | if (prot & PROT_EXEC) | ||
232 | rc = process_measurement(file, file->f_dentry->d_name.name, | ||
233 | MAY_EXEC, FILE_MMAP); | ||
234 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
235 | } | 232 | } |
236 | 233 | ||
237 | /** | 234 | /** |
@@ -244,18 +241,15 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
244 | * So we can be certain that what we verify and measure here is actually | 241 | * So we can be certain that what we verify and measure here is actually |
245 | * what is being executed. | 242 | * what is being executed. |
246 | * | 243 | * |
247 | * Return 0 on success, an error code on failure. | 244 | * On success return 0. On integrity appraisal error, assuming the file |
248 | * (Based on the results of appraise_measurement().) | 245 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
249 | */ | 246 | */ |
250 | int ima_bprm_check(struct linux_binprm *bprm) | 247 | int ima_bprm_check(struct linux_binprm *bprm) |
251 | { | 248 | { |
252 | int rc; | 249 | return process_measurement(bprm->file, |
253 | |||
254 | rc = process_measurement(bprm->file, | ||
255 | (strcmp(bprm->filename, bprm->interp) == 0) ? | 250 | (strcmp(bprm->filename, bprm->interp) == 0) ? |
256 | bprm->filename : bprm->interp, | 251 | bprm->filename : bprm->interp, |
257 | MAY_EXEC, BPRM_CHECK); | 252 | MAY_EXEC, BPRM_CHECK); |
258 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
259 | } | 253 | } |
260 | 254 | ||
261 | /** | 255 | /** |
@@ -265,18 +259,15 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
265 | * | 259 | * |
266 | * Measure files based on the ima_must_measure() policy decision. | 260 | * Measure files based on the ima_must_measure() policy decision. |
267 | * | 261 | * |
268 | * Always return 0 and audit dentry_open failures. | 262 | * On success return 0. On integrity appraisal error, assuming the file |
269 | * (Return code will be based upon measurement appraisal.) | 263 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
270 | */ | 264 | */ |
271 | int ima_file_check(struct file *file, int mask) | 265 | int ima_file_check(struct file *file, int mask) |
272 | { | 266 | { |
273 | int rc; | ||
274 | |||
275 | ima_rdwr_violation_check(file); | 267 | ima_rdwr_violation_check(file); |
276 | rc = process_measurement(file, file->f_dentry->d_name.name, | 268 | return process_measurement(file, file->f_dentry->d_name.name, |
277 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 269 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
278 | FILE_CHECK); | 270 | FILE_CHECK); |
279 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
280 | } | 271 | } |
281 | EXPORT_SYMBOL_GPL(ima_file_check); | 272 | EXPORT_SYMBOL_GPL(ima_file_check); |
282 | 273 | ||
@@ -286,23 +277,20 @@ EXPORT_SYMBOL_GPL(ima_file_check); | |||
286 | * | 277 | * |
287 | * Measure/appraise kernel modules based on policy. | 278 | * Measure/appraise kernel modules based on policy. |
288 | * | 279 | * |
289 | * Always return 0 and audit dentry_open failures. | 280 | * On success return 0. On integrity appraisal error, assuming the file |
290 | * Return code is based upon measurement appraisal. | 281 | * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. |
291 | */ | 282 | */ |
292 | int ima_module_check(struct file *file) | 283 | int ima_module_check(struct file *file) |
293 | { | 284 | { |
294 | int rc = 0; | ||
295 | |||
296 | if (!file) { | 285 | if (!file) { |
297 | if (ima_appraise & IMA_APPRAISE_MODULES) { | ||
298 | #ifndef CONFIG_MODULE_SIG_FORCE | 286 | #ifndef CONFIG_MODULE_SIG_FORCE |
299 | rc = -EACCES; /* INTEGRITY_UNKNOWN */ | 287 | if (ima_appraise & IMA_APPRAISE_MODULES) |
288 | return -EACCES; /* INTEGRITY_UNKNOWN */ | ||
300 | #endif | 289 | #endif |
301 | } | 290 | return 0; /* We rely on module signature checking */ |
302 | } else | 291 | } |
303 | rc = process_measurement(file, file->f_dentry->d_name.name, | 292 | return process_measurement(file, file->f_dentry->d_name.name, |
304 | MAY_EXEC, MODULE_CHECK); | 293 | MAY_EXEC, MODULE_CHECK); |
305 | return (ima_appraise & IMA_APPRAISE_ENFORCE) ? rc : 0; | ||
306 | } | 294 | } |
307 | 295 | ||
308 | static int __init init_ima(void) | 296 | static int __init init_ima(void) |