diff options
author | Dmitry Kasatkin <dmitry.kasatkin@intel.com> | 2011-10-19 05:04:40 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2012-09-07 14:57:45 -0400 |
commit | bf2276d10ce58ff44ab8857266a6718024496af6 (patch) | |
tree | 7be39c026fd30856248f68c964d0f1e2ae703c25 | |
parent | 07f6a79415d7d502ee0c7d02ace6594a7be7429a (diff) |
ima: allocating iint improvements
With IMA-appraisal's removal of the iint mutex and taking the i_mutex
instead, allocating the iint becomes a lot simplier, as we don't need
to be concerned with two processes racing to allocate the iint. This
patch cleans up and improves performance for allocating the iint.
- removed redundant double i_mutex locking
- combined iint allocation with tree search
Changelog v2:
- removed the rwlock/read_lock changes from this patch
Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
-rw-r--r-- | include/linux/integrity.h | 7 | ||||
-rw-r--r-- | security/integrity/iint.c | 45 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 13 |
3 files changed, 27 insertions, 38 deletions
diff --git a/include/linux/integrity.h b/include/linux/integrity.h index a0c41256cb92..66c5fe9550a5 100644 --- a/include/linux/integrity.h +++ b/include/linux/integrity.h | |||
@@ -22,13 +22,14 @@ enum integrity_status { | |||
22 | 22 | ||
23 | /* List of EVM protected security xattrs */ | 23 | /* List of EVM protected security xattrs */ |
24 | #ifdef CONFIG_INTEGRITY | 24 | #ifdef CONFIG_INTEGRITY |
25 | extern int integrity_inode_alloc(struct inode *inode); | 25 | extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode); |
26 | extern void integrity_inode_free(struct inode *inode); | 26 | extern void integrity_inode_free(struct inode *inode); |
27 | 27 | ||
28 | #else | 28 | #else |
29 | static inline int integrity_inode_alloc(struct inode *inode) | 29 | static inline struct integrity_iint_cache * |
30 | integrity_inode_get(struct inode *inode) | ||
30 | { | 31 | { |
31 | return 0; | 32 | return NULL; |
32 | } | 33 | } |
33 | 34 | ||
34 | static inline void integrity_inode_free(struct inode *inode) | 35 | static inline void integrity_inode_free(struct inode *inode) |
diff --git a/security/integrity/iint.c b/security/integrity/iint.c index e600986aa49f..c91a436e13ac 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c | |||
@@ -80,24 +80,26 @@ static void iint_free(struct integrity_iint_cache *iint) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | /** | 82 | /** |
83 | * integrity_inode_alloc - allocate an iint associated with an inode | 83 | * integrity_inode_get - find or allocate an iint associated with an inode |
84 | * @inode: pointer to the inode | 84 | * @inode: pointer to the inode |
85 | * @return: allocated iint | ||
86 | * | ||
87 | * Caller must lock i_mutex | ||
85 | */ | 88 | */ |
86 | int integrity_inode_alloc(struct inode *inode) | 89 | struct integrity_iint_cache *integrity_inode_get(struct inode *inode) |
87 | { | 90 | { |
88 | struct rb_node **p; | 91 | struct rb_node **p; |
89 | struct rb_node *new_node, *parent = NULL; | 92 | struct rb_node *node, *parent = NULL; |
90 | struct integrity_iint_cache *new_iint, *test_iint; | 93 | struct integrity_iint_cache *iint, *test_iint; |
91 | int rc; | ||
92 | 94 | ||
93 | new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | 95 | iint = integrity_iint_find(inode); |
94 | if (!new_iint) | 96 | if (iint) |
95 | return -ENOMEM; | 97 | return iint; |
96 | 98 | ||
97 | new_iint->inode = inode; | 99 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); |
98 | new_node = &new_iint->rb_node; | 100 | if (!iint) |
101 | return NULL; | ||
99 | 102 | ||
100 | mutex_lock(&inode->i_mutex); /* i_flags */ | ||
101 | spin_lock(&integrity_iint_lock); | 103 | spin_lock(&integrity_iint_lock); |
102 | 104 | ||
103 | p = &integrity_iint_tree.rb_node; | 105 | p = &integrity_iint_tree.rb_node; |
@@ -105,29 +107,20 @@ int integrity_inode_alloc(struct inode *inode) | |||
105 | parent = *p; | 107 | parent = *p; |
106 | test_iint = rb_entry(parent, struct integrity_iint_cache, | 108 | test_iint = rb_entry(parent, struct integrity_iint_cache, |
107 | rb_node); | 109 | rb_node); |
108 | rc = -EEXIST; | ||
109 | if (inode < test_iint->inode) | 110 | if (inode < test_iint->inode) |
110 | p = &(*p)->rb_left; | 111 | p = &(*p)->rb_left; |
111 | else if (inode > test_iint->inode) | ||
112 | p = &(*p)->rb_right; | ||
113 | else | 112 | else |
114 | goto out_err; | 113 | p = &(*p)->rb_right; |
115 | } | 114 | } |
116 | 115 | ||
116 | iint->inode = inode; | ||
117 | node = &iint->rb_node; | ||
117 | inode->i_flags |= S_IMA; | 118 | inode->i_flags |= S_IMA; |
118 | rb_link_node(new_node, parent, p); | 119 | rb_link_node(node, parent, p); |
119 | rb_insert_color(new_node, &integrity_iint_tree); | 120 | rb_insert_color(node, &integrity_iint_tree); |
120 | 121 | ||
121 | spin_unlock(&integrity_iint_lock); | 122 | spin_unlock(&integrity_iint_lock); |
122 | mutex_unlock(&inode->i_mutex); /* i_flags */ | 123 | return iint; |
123 | |||
124 | return 0; | ||
125 | out_err: | ||
126 | spin_unlock(&integrity_iint_lock); | ||
127 | mutex_unlock(&inode->i_mutex); /* i_flags */ | ||
128 | iint_free(new_iint); | ||
129 | |||
130 | return rc; | ||
131 | } | 124 | } |
132 | 125 | ||
133 | /** | 126 | /** |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 6eb28d47e74b..df6521296051 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -162,19 +162,14 @@ static int process_measurement(struct file *file, const unsigned char *filename, | |||
162 | if (!action) | 162 | if (!action) |
163 | return 0; | 163 | return 0; |
164 | 164 | ||
165 | retry: | ||
166 | iint = integrity_iint_find(inode); | ||
167 | if (!iint) { | ||
168 | rc = integrity_inode_alloc(inode); | ||
169 | if (!rc || rc == -EEXIST) | ||
170 | goto retry; | ||
171 | return rc; | ||
172 | } | ||
173 | |||
174 | must_appraise = action & IMA_APPRAISE; | 165 | must_appraise = action & IMA_APPRAISE; |
175 | 166 | ||
176 | mutex_lock(&inode->i_mutex); | 167 | mutex_lock(&inode->i_mutex); |
177 | 168 | ||
169 | iint = integrity_inode_get(inode); | ||
170 | if (!iint) | ||
171 | goto out; | ||
172 | |||
178 | /* Determine if already appraised/measured based on bitmask | 173 | /* Determine if already appraised/measured based on bitmask |
179 | * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED) */ | 174 | * (IMA_MEASURE, IMA_MEASURED, IMA_APPRAISE, IMA_APPRAISED) */ |
180 | iint->flags |= action; | 175 | iint->flags |= action; |