diff options
| -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 | ||
