diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
| -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); |
