diff options
Diffstat (limited to 'security/selinux/ss/sidtab.c')
| -rw-r--r-- | security/selinux/ss/sidtab.c | 39 | 
1 files changed, 37 insertions, 2 deletions
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index e817989764c..5840a35155f 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -147,6 +147,17 @@ out:  	return rc;  } +static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc) +{ +	BUG_ON(loc >= SIDTAB_CACHE_LEN); + +	while (loc > 0) { +		s->cache[loc] = s->cache[loc - 1]; +		loc--; +	} +	s->cache[0] = n; +} +  static inline u32 sidtab_search_context(struct sidtab *s,  						  struct context *context)  { @@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s,  	for (i = 0; i < SIDTAB_SIZE; i++) {  		cur = s->htable[i];  		while (cur) { -			if (context_cmp(&cur->context, context)) +			if (context_cmp(&cur->context, context)) { +				sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1);  				return cur->sid; +			}  			cur = cur->next;  		}  	}  	return 0;  } +static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context) +{ +	int i; +	struct sidtab_node *node; + +	for (i = 0; i < SIDTAB_CACHE_LEN; i++) { +		node = s->cache[i]; +		if (unlikely(!node)) +			return 0; +		if (context_cmp(&node->context, context)) { +			sidtab_update_cache(s, node, i); +			return node->sid; +		} +	} +	return 0; +} +  int sidtab_context_to_sid(struct sidtab *s,  			  struct context *context,  			  u32 *out_sid) @@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s,  	*out_sid = SECSID_NULL; -	sid = sidtab_search_context(s, context); +	sid  = sidtab_search_cache(s, context); +	if (!sid) +		sid = sidtab_search_context(s, context);  	if (!sid) {  		spin_lock_irqsave(&s->lock, flags);  		/* Rescan now that we hold the lock. */ @@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s)  void sidtab_set(struct sidtab *dst, struct sidtab *src)  {  	unsigned long flags; +	int i;  	spin_lock_irqsave(&src->lock, flags);  	dst->htable = src->htable;  	dst->nel = src->nel;  	dst->next_sid = src->next_sid;  	dst->shutdown = 0; +	for (i = 0; i < SIDTAB_CACHE_LEN; i++) +		dst->cache[i] = NULL;  	spin_unlock_irqrestore(&src->lock, flags);  }  | 
