aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/avc.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 9dd5c506a826..7f9b5fac8779 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -92,12 +92,12 @@ struct avc_entry {
92 92
93struct avc_node { 93struct avc_node {
94 struct avc_entry ae; 94 struct avc_entry ae;
95 struct list_head list; /* anchored in avc_cache->slots[i] */ 95 struct hlist_node list; /* anchored in avc_cache->slots[i] */
96 struct rcu_head rhead; 96 struct rcu_head rhead;
97}; 97};
98 98
99struct avc_cache { 99struct avc_cache {
100 struct list_head slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */ 100 struct hlist_head slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
101 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */ 101 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
102 atomic_t lru_hint; /* LRU hint for reclaim scan */ 102 atomic_t lru_hint; /* LRU hint for reclaim scan */
103 atomic_t active_nodes; 103 atomic_t active_nodes;
@@ -233,7 +233,7 @@ void __init avc_init(void)
233 int i; 233 int i;
234 234
235 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 235 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
236 INIT_LIST_HEAD(&avc_cache.slots[i]); 236 INIT_HLIST_HEAD(&avc_cache.slots[i]);
237 spin_lock_init(&avc_cache.slots_lock[i]); 237 spin_lock_init(&avc_cache.slots_lock[i]);
238 } 238 }
239 atomic_set(&avc_cache.active_nodes, 0); 239 atomic_set(&avc_cache.active_nodes, 0);
@@ -249,7 +249,7 @@ int avc_get_hash_stats(char *page)
249{ 249{
250 int i, chain_len, max_chain_len, slots_used; 250 int i, chain_len, max_chain_len, slots_used;
251 struct avc_node *node; 251 struct avc_node *node;
252 struct list_head *head; 252 struct hlist_head *head;
253 253
254 rcu_read_lock(); 254 rcu_read_lock();
255 255
@@ -257,10 +257,12 @@ int avc_get_hash_stats(char *page)
257 max_chain_len = 0; 257 max_chain_len = 0;
258 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 258 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
259 head = &avc_cache.slots[i]; 259 head = &avc_cache.slots[i];
260 if (!list_empty(head)) { 260 if (!hlist_empty(head)) {
261 struct hlist_node *next;
262
261 slots_used++; 263 slots_used++;
262 chain_len = 0; 264 chain_len = 0;
263 list_for_each_entry_rcu(node, head, list) 265 hlist_for_each_entry_rcu(node, next, head, list)
264 chain_len++; 266 chain_len++;
265 if (chain_len > max_chain_len) 267 if (chain_len > max_chain_len)
266 max_chain_len = chain_len; 268 max_chain_len = chain_len;
@@ -284,7 +286,7 @@ static void avc_node_free(struct rcu_head *rhead)
284 286
285static void avc_node_delete(struct avc_node *node) 287static void avc_node_delete(struct avc_node *node)
286{ 288{
287 list_del_rcu(&node->list); 289 hlist_del_rcu(&node->list);
288 call_rcu(&node->rhead, avc_node_free); 290 call_rcu(&node->rhead, avc_node_free);
289 atomic_dec(&avc_cache.active_nodes); 291 atomic_dec(&avc_cache.active_nodes);
290} 292}
@@ -298,7 +300,7 @@ static void avc_node_kill(struct avc_node *node)
298 300
299static void avc_node_replace(struct avc_node *new, struct avc_node *old) 301static void avc_node_replace(struct avc_node *new, struct avc_node *old)
300{ 302{
301 list_replace_rcu(&old->list, &new->list); 303 hlist_replace_rcu(&old->list, &new->list);
302 call_rcu(&old->rhead, avc_node_free); 304 call_rcu(&old->rhead, avc_node_free);
303 atomic_dec(&avc_cache.active_nodes); 305 atomic_dec(&avc_cache.active_nodes);
304} 306}
@@ -308,7 +310,8 @@ static inline int avc_reclaim_node(void)
308 struct avc_node *node; 310 struct avc_node *node;
309 int hvalue, try, ecx; 311 int hvalue, try, ecx;
310 unsigned long flags; 312 unsigned long flags;
311 struct list_head *head; 313 struct hlist_head *head;
314 struct hlist_node *next;
312 spinlock_t *lock; 315 spinlock_t *lock;
313 316
314 for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) { 317 for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
@@ -320,7 +323,7 @@ static inline int avc_reclaim_node(void)
320 continue; 323 continue;
321 324
322 rcu_read_lock(); 325 rcu_read_lock();
323 list_for_each_entry(node, head, list) { 326 hlist_for_each_entry(node, next, head, list) {
324 avc_node_delete(node); 327 avc_node_delete(node);
325 avc_cache_stats_incr(reclaims); 328 avc_cache_stats_incr(reclaims);
326 ecx++; 329 ecx++;
@@ -346,7 +349,7 @@ static struct avc_node *avc_alloc_node(void)
346 goto out; 349 goto out;
347 350
348 INIT_RCU_HEAD(&node->rhead); 351 INIT_RCU_HEAD(&node->rhead);
349 INIT_LIST_HEAD(&node->list); 352 INIT_HLIST_NODE(&node->list);
350 avc_cache_stats_incr(allocations); 353 avc_cache_stats_incr(allocations);
351 354
352 if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold) 355 if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold)
@@ -368,11 +371,12 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
368{ 371{
369 struct avc_node *node, *ret = NULL; 372 struct avc_node *node, *ret = NULL;
370 int hvalue; 373 int hvalue;
371 struct list_head *head; 374 struct hlist_head *head;
375 struct hlist_node *next;
372 376
373 hvalue = avc_hash(ssid, tsid, tclass); 377 hvalue = avc_hash(ssid, tsid, tclass);
374 head = &avc_cache.slots[hvalue]; 378 head = &avc_cache.slots[hvalue];
375 list_for_each_entry_rcu(node, head, list) { 379 hlist_for_each_entry_rcu(node, next, head, list) {
376 if (ssid == node->ae.ssid && 380 if (ssid == node->ae.ssid &&
377 tclass == node->ae.tclass && 381 tclass == node->ae.tclass &&
378 tsid == node->ae.tsid) { 382 tsid == node->ae.tsid) {
@@ -461,7 +465,8 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
461 465
462 node = avc_alloc_node(); 466 node = avc_alloc_node();
463 if (node) { 467 if (node) {
464 struct list_head *head; 468 struct hlist_head *head;
469 struct hlist_node *next;
465 spinlock_t *lock; 470 spinlock_t *lock;
466 471
467 hvalue = avc_hash(ssid, tsid, tclass); 472 hvalue = avc_hash(ssid, tsid, tclass);
@@ -471,7 +476,7 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
471 lock = &avc_cache.slots_lock[hvalue]; 476 lock = &avc_cache.slots_lock[hvalue];
472 477
473 spin_lock_irqsave(lock, flag); 478 spin_lock_irqsave(lock, flag);
474 list_for_each_entry(pos, head, list) { 479 hlist_for_each_entry(pos, next, head, list) {
475 if (pos->ae.ssid == ssid && 480 if (pos->ae.ssid == ssid &&
476 pos->ae.tsid == tsid && 481 pos->ae.tsid == tsid &&
477 pos->ae.tclass == tclass) { 482 pos->ae.tclass == tclass) {
@@ -479,7 +484,7 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_dec
479 goto found; 484 goto found;
480 } 485 }
481 } 486 }
482 list_add_rcu(&node->list, head); 487 hlist_add_head_rcu(&node->list, head);
483found: 488found:
484 spin_unlock_irqrestore(lock, flag); 489 spin_unlock_irqrestore(lock, flag);
485 } 490 }
@@ -750,7 +755,8 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
750 int hvalue, rc = 0; 755 int hvalue, rc = 0;
751 unsigned long flag; 756 unsigned long flag;
752 struct avc_node *pos, *node, *orig = NULL; 757 struct avc_node *pos, *node, *orig = NULL;
753 struct list_head *head; 758 struct hlist_head *head;
759 struct hlist_node *next;
754 spinlock_t *lock; 760 spinlock_t *lock;
755 761
756 node = avc_alloc_node(); 762 node = avc_alloc_node();
@@ -767,7 +773,7 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
767 773
768 spin_lock_irqsave(lock, flag); 774 spin_lock_irqsave(lock, flag);
769 775
770 list_for_each_entry(pos, head, list) { 776 hlist_for_each_entry(pos, next, head, list) {
771 if (ssid == pos->ae.ssid && 777 if (ssid == pos->ae.ssid &&
772 tsid == pos->ae.tsid && 778 tsid == pos->ae.tsid &&
773 tclass == pos->ae.tclass && 779 tclass == pos->ae.tclass &&
@@ -827,7 +833,8 @@ int avc_ss_reset(u32 seqno)
827 int i, rc = 0, tmprc; 833 int i, rc = 0, tmprc;
828 unsigned long flag; 834 unsigned long flag;
829 struct avc_node *node; 835 struct avc_node *node;
830 struct list_head *head; 836 struct hlist_head *head;
837 struct hlist_node *next;
831 spinlock_t *lock; 838 spinlock_t *lock;
832 839
833 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 840 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
@@ -840,7 +847,7 @@ int avc_ss_reset(u32 seqno)
840 * prevent RCU grace periods from ending. 847 * prevent RCU grace periods from ending.
841 */ 848 */
842 rcu_read_lock(); 849 rcu_read_lock();
843 list_for_each_entry(node, head, list) 850 hlist_for_each_entry(node, next, head, list)
844 avc_node_delete(node); 851 avc_node_delete(node);
845 rcu_read_unlock(); 852 rcu_read_unlock();
846 spin_unlock_irqrestore(lock, flag); 853 spin_unlock_irqrestore(lock, flag);