diff options
-rw-r--r-- | security/integrity/ima/ima_main.c | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 16dc57d247d0..a89f44d5e030 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -35,6 +35,55 @@ static int __init hash_setup(char *str) | |||
35 | } | 35 | } |
36 | __setup("ima_hash=", hash_setup); | 36 | __setup("ima_hash=", hash_setup); |
37 | 37 | ||
38 | struct ima_imbalance { | ||
39 | struct hlist_node node; | ||
40 | unsigned long fsmagic; | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * ima_limit_imbalance - emit one imbalance message per filesystem type | ||
45 | * | ||
46 | * Maintain list of filesystem types that do not measure files properly. | ||
47 | * Return false if unknown, true if known. | ||
48 | */ | ||
49 | static bool ima_limit_imbalance(struct file *file) | ||
50 | { | ||
51 | static DEFINE_SPINLOCK(ima_imbalance_lock); | ||
52 | static HLIST_HEAD(ima_imbalance_list); | ||
53 | |||
54 | struct super_block *sb = file->f_dentry->d_sb; | ||
55 | struct ima_imbalance *entry; | ||
56 | struct hlist_node *node; | ||
57 | bool found = false; | ||
58 | |||
59 | rcu_read_lock(); | ||
60 | hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) { | ||
61 | if (entry->fsmagic == sb->s_magic) { | ||
62 | found = true; | ||
63 | break; | ||
64 | } | ||
65 | } | ||
66 | rcu_read_unlock(); | ||
67 | if (found) | ||
68 | goto out; | ||
69 | |||
70 | entry = kmalloc(sizeof(*entry), GFP_NOFS); | ||
71 | if (!entry) | ||
72 | goto out; | ||
73 | entry->fsmagic = sb->s_magic; | ||
74 | spin_lock(&ima_imbalance_lock); | ||
75 | /* | ||
76 | * we could have raced and something else might have added this fs | ||
77 | * to the list, but we don't really care | ||
78 | */ | ||
79 | hlist_add_head_rcu(&entry->node, &ima_imbalance_list); | ||
80 | spin_unlock(&ima_imbalance_lock); | ||
81 | printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n", | ||
82 | entry->fsmagic); | ||
83 | out: | ||
84 | return found; | ||
85 | } | ||
86 | |||
38 | /* | 87 | /* |
39 | * Update the counts given an fmode_t | 88 | * Update the counts given an fmode_t |
40 | */ | 89 | */ |
@@ -69,15 +118,10 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | |||
69 | } | 118 | } |
70 | } | 119 | } |
71 | 120 | ||
72 | if ((iint->opencount < 0) || | 121 | if (((iint->opencount < 0) || |
73 | (iint->readcount < 0) || | 122 | (iint->readcount < 0) || |
74 | (iint->writecount < 0)) { | 123 | (iint->writecount < 0)) && |
75 | static int dumped; | 124 | !ima_limit_imbalance(file)) { |
76 | |||
77 | if (dumped) | ||
78 | return; | ||
79 | dumped = 1; | ||
80 | |||
81 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", | 125 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", |
82 | __FUNCTION__, iint->readcount, iint->writecount, | 126 | __FUNCTION__, iint->readcount, iint->writecount, |
83 | iint->opencount); | 127 | iint->opencount); |