diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/ss/sidtab.c | 39 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.h | 2 |
2 files changed, 39 insertions, 2 deletions
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index e817989764cd..5840a35155fc 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
@@ -147,6 +147,17 @@ out: | |||
147 | return rc; | 147 | return rc; |
148 | } | 148 | } |
149 | 149 | ||
150 | static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc) | ||
151 | { | ||
152 | BUG_ON(loc >= SIDTAB_CACHE_LEN); | ||
153 | |||
154 | while (loc > 0) { | ||
155 | s->cache[loc] = s->cache[loc - 1]; | ||
156 | loc--; | ||
157 | } | ||
158 | s->cache[0] = n; | ||
159 | } | ||
160 | |||
150 | static inline u32 sidtab_search_context(struct sidtab *s, | 161 | static inline u32 sidtab_search_context(struct sidtab *s, |
151 | struct context *context) | 162 | struct context *context) |
152 | { | 163 | { |
@@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s, | |||
156 | for (i = 0; i < SIDTAB_SIZE; i++) { | 167 | for (i = 0; i < SIDTAB_SIZE; i++) { |
157 | cur = s->htable[i]; | 168 | cur = s->htable[i]; |
158 | while (cur) { | 169 | while (cur) { |
159 | if (context_cmp(&cur->context, context)) | 170 | if (context_cmp(&cur->context, context)) { |
171 | sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1); | ||
160 | return cur->sid; | 172 | return cur->sid; |
173 | } | ||
161 | cur = cur->next; | 174 | cur = cur->next; |
162 | } | 175 | } |
163 | } | 176 | } |
164 | return 0; | 177 | return 0; |
165 | } | 178 | } |
166 | 179 | ||
180 | static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context) | ||
181 | { | ||
182 | int i; | ||
183 | struct sidtab_node *node; | ||
184 | |||
185 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) { | ||
186 | node = s->cache[i]; | ||
187 | if (unlikely(!node)) | ||
188 | return 0; | ||
189 | if (context_cmp(&node->context, context)) { | ||
190 | sidtab_update_cache(s, node, i); | ||
191 | return node->sid; | ||
192 | } | ||
193 | } | ||
194 | return 0; | ||
195 | } | ||
196 | |||
167 | int sidtab_context_to_sid(struct sidtab *s, | 197 | int sidtab_context_to_sid(struct sidtab *s, |
168 | struct context *context, | 198 | struct context *context, |
169 | u32 *out_sid) | 199 | u32 *out_sid) |
@@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s, | |||
174 | 204 | ||
175 | *out_sid = SECSID_NULL; | 205 | *out_sid = SECSID_NULL; |
176 | 206 | ||
177 | sid = sidtab_search_context(s, context); | 207 | sid = sidtab_search_cache(s, context); |
208 | if (!sid) | ||
209 | sid = sidtab_search_context(s, context); | ||
178 | if (!sid) { | 210 | if (!sid) { |
179 | spin_lock_irqsave(&s->lock, flags); | 211 | spin_lock_irqsave(&s->lock, flags); |
180 | /* Rescan now that we hold the lock. */ | 212 | /* Rescan now that we hold the lock. */ |
@@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s) | |||
259 | void sidtab_set(struct sidtab *dst, struct sidtab *src) | 291 | void sidtab_set(struct sidtab *dst, struct sidtab *src) |
260 | { | 292 | { |
261 | unsigned long flags; | 293 | unsigned long flags; |
294 | int i; | ||
262 | 295 | ||
263 | spin_lock_irqsave(&src->lock, flags); | 296 | spin_lock_irqsave(&src->lock, flags); |
264 | dst->htable = src->htable; | 297 | dst->htable = src->htable; |
265 | dst->nel = src->nel; | 298 | dst->nel = src->nel; |
266 | dst->next_sid = src->next_sid; | 299 | dst->next_sid = src->next_sid; |
267 | dst->shutdown = 0; | 300 | dst->shutdown = 0; |
301 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) | ||
302 | dst->cache[i] = NULL; | ||
268 | spin_unlock_irqrestore(&src->lock, flags); | 303 | spin_unlock_irqrestore(&src->lock, flags); |
269 | } | 304 | } |
270 | 305 | ||
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 64ea5b1cdea4..84dc154d9389 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h | |||
@@ -26,6 +26,8 @@ struct sidtab { | |||
26 | unsigned int nel; /* number of elements */ | 26 | unsigned int nel; /* number of elements */ |
27 | unsigned int next_sid; /* next SID to allocate */ | 27 | unsigned int next_sid; /* next SID to allocate */ |
28 | unsigned char shutdown; | 28 | unsigned char shutdown; |
29 | #define SIDTAB_CACHE_LEN 3 | ||
30 | struct sidtab_node *cache[SIDTAB_CACHE_LEN]; | ||
29 | spinlock_t lock; | 31 | spinlock_t lock; |
30 | }; | 32 | }; |
31 | 33 | ||