aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2014-10-03 07:40:21 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2014-10-11 23:33:02 -0400
commit0716abbb58e3c47e04354c2502083854f49c34e5 (patch)
treea4c5c40884a7bcb9cdf12d6e7184fe19699b1894 /security
parent7178784f0a94e2e6c668f587665fde41d405a23c (diff)
ima: use atomic bit operations to protect policy update interface
The current implementation uses an atomic counter to provide exclusive access to the sysfs 'policy' entry to update the IMA policy. While it is highly unlikely, the usage of a counter might potentially allow another process to overflow the counter, open the interface and insert additional rules into the policy being loaded. This patch replaces using an atomic counter with atomic bit operations which is more reliable and a widely used method to provide exclusive access. As bit operation keep the interface locked after successful update, it makes it unnecessary to verify if the default policy was set or not during parsing and interface closing. This patch also removes that code. Changes in v3: * move audit log message to ima_relead_policy() to report successful and unsuccessful result * unnecessary comment removed Changes in v2: * keep interface locked after successful policy load as in original design * remove sysfs entry as in original design Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security')
-rw-r--r--security/integrity/ima/ima_fs.c23
-rw-r--r--security/integrity/ima/ima_policy.c23
2 files changed, 18 insertions, 28 deletions
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 16d85273d408..973b5683a92e 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -288,7 +288,12 @@ static struct dentry *runtime_measurements_count;
288static struct dentry *violations; 288static struct dentry *violations;
289static struct dentry *ima_policy; 289static struct dentry *ima_policy;
290 290
291static atomic_t policy_opencount = ATOMIC_INIT(1); 291enum ima_fs_flags {
292 IMA_FS_BUSY,
293};
294
295static unsigned long ima_fs_flags;
296
292/* 297/*
293 * ima_open_policy: sequentialize access to the policy file 298 * ima_open_policy: sequentialize access to the policy file
294 */ 299 */
@@ -297,9 +302,9 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
297 /* No point in being allowed to open it if you aren't going to write */ 302 /* No point in being allowed to open it if you aren't going to write */
298 if (!(filp->f_flags & O_WRONLY)) 303 if (!(filp->f_flags & O_WRONLY))
299 return -EACCES; 304 return -EACCES;
300 if (atomic_dec_and_test(&policy_opencount)) 305 if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags))
301 return 0; 306 return -EBUSY;
302 return -EBUSY; 307 return 0;
303} 308}
304 309
305/* 310/*
@@ -311,12 +316,16 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
311 */ 316 */
312static int ima_release_policy(struct inode *inode, struct file *file) 317static int ima_release_policy(struct inode *inode, struct file *file)
313{ 318{
314 pr_info("IMA: policy update %s\n", 319 const char *cause = valid_policy ? "completed" : "failed";
315 valid_policy ? "completed" : "failed"); 320
321 pr_info("IMA: policy update %s\n", cause);
322 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
323 "policy_update", cause, !valid_policy, 0);
324
316 if (!valid_policy) { 325 if (!valid_policy) {
317 ima_delete_rules(); 326 ima_delete_rules();
318 valid_policy = 1; 327 valid_policy = 1;
319 atomic_set(&policy_opencount, 1); 328 clear_bit(IMA_FS_BUSY, &ima_fs_flags);
320 return 0; 329 return 0;
321 } 330 }
322 ima_update_policy(); 331 ima_update_policy();
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index d2c47d4df7b7..0d14d2591805 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -356,19 +356,8 @@ void __init ima_init_policy(void)
356 */ 356 */
357void ima_update_policy(void) 357void ima_update_policy(void)
358{ 358{
359 static const char op[] = "policy_update"; 359 ima_rules = &ima_policy_rules;
360 const char *cause = "already-exists"; 360 ima_update_policy_flag();
361 int result = 1;
362 int audit_info = 0;
363
364 if (ima_rules == &ima_default_rules) {
365 ima_rules = &ima_policy_rules;
366 ima_update_policy_flag();
367 cause = "complete";
368 result = 0;
369 }
370 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
371 NULL, op, cause, result, audit_info);
372} 361}
373 362
374enum { 363enum {
@@ -686,14 +675,6 @@ ssize_t ima_parse_add_rule(char *rule)
686 ssize_t result, len; 675 ssize_t result, len;
687 int audit_info = 0; 676 int audit_info = 0;
688 677
689 /* Prevent installed policy from changing */
690 if (ima_rules != &ima_default_rules) {
691 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
692 NULL, op, "already-exists",
693 -EACCES, audit_info);
694 return -EACCES;
695 }
696
697 p = strsep(&rule, "\n"); 678 p = strsep(&rule, "\n");
698 len = strlen(p) + 1; 679 len = strlen(p) + 1;
699 p += strspn(p, " \t"); 680 p += strspn(p, " \t");