Lines Matching +full:keep +full:- +full:a +full:- +full:live
1 // SPDX-License-Identifier: GPL-2.0
33 #define sid_to_index(sid) ((sid) - (SECINITSID_NUM + 1))
39 memset(s->roots, 0, sizeof(s->roots)); in sidtab_init()
42 s->isids[i].set = 0; in sidtab_init()
44 s->frozen = false; in sidtab_init()
45 s->count = 0; in sidtab_init()
46 s->convert = NULL; in sidtab_init()
47 hash_init(s->context_to_sid); in sidtab_init()
49 spin_lock_init(&s->lock); in sidtab_init()
52 s->cache_free_slots = CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE; in sidtab_init()
53 INIT_LIST_HEAD(&s->cache_lru_list); in sidtab_init()
54 spin_lock_init(&s->cache_lock); in sidtab_init()
66 hash_for_each_possible_rcu(s->context_to_sid, entry, list, hash) { in context_to_sid()
67 if (entry->hash != hash) in context_to_sid()
69 if (context_equal(&entry->context, context)) { in context_to_sid()
70 sid = entry->sid; in context_to_sid()
85 return -EINVAL; in sidtab_set_initial()
87 isid = &s->isids[sid - 1]; in sidtab_set_initial()
89 rc = context_cpy(&isid->entry.context, context); in sidtab_set_initial()
94 isid->entry.cache = NULL; in sidtab_set_initial()
96 isid->set = 1; in sidtab_set_initial()
107 isid->entry.sid = sid; in sidtab_set_initial()
108 isid->entry.hash = hash; in sidtab_set_initial()
109 hash_add(s->context_to_sid, &isid->entry.list, hash); in sidtab_set_initial()
126 hash_for_each_rcu(sidtab->context_to_sid, i, entry, list) { in sidtab_hash_stats()
167 if (!s->roots[0].ptr_leaf) { in sidtab_alloc_roots()
168 s->roots[0].ptr_leaf = in sidtab_alloc_roots()
170 if (!s->roots[0].ptr_leaf) in sidtab_alloc_roots()
171 return -ENOMEM; in sidtab_alloc_roots()
174 if (!s->roots[l].ptr_inner) { in sidtab_alloc_roots()
175 s->roots[l].ptr_inner = in sidtab_alloc_roots()
177 if (!s->roots[l].ptr_inner) in sidtab_alloc_roots()
178 return -ENOMEM; in sidtab_alloc_roots()
179 s->roots[l].ptr_inner->entries[0] = s->roots[l - 1]; in sidtab_alloc_roots()
199 entry = &s->roots[level]; in sidtab_do_lookup()
201 capacity_shift -= SIDTAB_INNER_SHIFT; in sidtab_do_lookup()
202 --level; in sidtab_do_lookup()
204 entry = &entry->ptr_inner->entries[leaf_index >> capacity_shift]; in sidtab_do_lookup()
205 leaf_index &= ((u32)1 << capacity_shift) - 1; in sidtab_do_lookup()
207 if (!entry->ptr_inner) { in sidtab_do_lookup()
209 entry->ptr_inner = kzalloc( in sidtab_do_lookup()
211 if (!entry->ptr_inner) in sidtab_do_lookup()
215 if (!entry->ptr_leaf) { in sidtab_do_lookup()
217 entry->ptr_leaf = in sidtab_do_lookup()
219 if (!entry->ptr_leaf) in sidtab_do_lookup()
222 return &entry->ptr_leaf->entries[index % SIDTAB_LEAF_ENTRIES]; in sidtab_do_lookup()
228 u32 count = smp_load_acquire(&s->count); in sidtab_lookup()
238 return s->isids[sid - 1].set ? &s->isids[sid - 1].entry : NULL; in sidtab_lookup_initial()
251 if (entry && (!entry->context.len || force)) in sidtab_search_core()
280 /* lock-free search failed: lock, re-search, and insert if not found */ in sidtab_context_to_sid()
281 spin_lock_irqsave(&s->lock, flags); in sidtab_context_to_sid()
288 if (unlikely(s->frozen)) { in sidtab_context_to_sid()
290 * This sidtab is now frozen - tell the caller to abort and in sidtab_context_to_sid()
293 rc = -ESTALE; in sidtab_context_to_sid()
297 count = s->count; in sidtab_context_to_sid()
300 rc = -EOVERFLOW; in sidtab_context_to_sid()
305 rc = -ENOMEM; in sidtab_context_to_sid()
310 dst->sid = index_to_sid(count); in sidtab_context_to_sid()
311 dst->hash = hash; in sidtab_context_to_sid()
313 rc = context_cpy(&dst->context, context); in sidtab_context_to_sid()
318 * if we are building a new sidtab, we need to convert the context in sidtab_context_to_sid()
321 convert = s->convert; in sidtab_context_to_sid()
323 struct sidtab *target = convert->target; in sidtab_context_to_sid()
325 rc = -ENOMEM; in sidtab_context_to_sid()
328 context_destroy(&dst->context); in sidtab_context_to_sid()
332 rc = services_convert_context(convert->args, context, in sidtab_context_to_sid()
333 &dst_convert->context, in sidtab_context_to_sid()
336 context_destroy(&dst->context); in sidtab_context_to_sid()
339 dst_convert->sid = index_to_sid(count); in sidtab_context_to_sid()
340 dst_convert->hash = context_compute_hash(&dst_convert->context); in sidtab_context_to_sid()
341 target->count = count + 1; in sidtab_context_to_sid()
343 hash_add_rcu(target->context_to_sid, &dst_convert->list, in sidtab_context_to_sid()
344 dst_convert->hash); in sidtab_context_to_sid()
347 if (context->len) in sidtab_context_to_sid()
349 context->str); in sidtab_context_to_sid()
354 smp_store_release(&s->count, count + 1); in sidtab_context_to_sid()
355 hash_add_rcu(s->context_to_sid, &dst->list, dst->hash); in sidtab_context_to_sid()
359 spin_unlock_irqrestore(&s->lock, flags); in sidtab_context_to_sid()
370 entry->sid = index_to_sid(i); in sidtab_convert_hashtable()
371 entry->hash = context_compute_hash(&entry->context); in sidtab_convert_hashtable()
373 hash_add_rcu(s->context_to_sid, &entry->list, entry->hash); in sidtab_convert_hashtable()
386 if (!edst->ptr_inner) { in sidtab_convert_tree()
387 edst->ptr_inner = in sidtab_convert_tree()
389 if (!edst->ptr_inner) in sidtab_convert_tree()
390 return -ENOMEM; in sidtab_convert_tree()
394 rc = sidtab_convert_tree(&edst->ptr_inner->entries[i], in sidtab_convert_tree()
395 &esrc->ptr_inner->entries[i], in sidtab_convert_tree()
396 pos, count, level - 1, in sidtab_convert_tree()
403 if (!edst->ptr_leaf) { in sidtab_convert_tree()
404 edst->ptr_leaf = in sidtab_convert_tree()
406 if (!edst->ptr_leaf) in sidtab_convert_tree()
407 return -ENOMEM; in sidtab_convert_tree()
412 convert->args, in sidtab_convert_tree()
413 &esrc->ptr_leaf->entries[i].context, in sidtab_convert_tree()
414 &edst->ptr_leaf->entries[i].context, in sidtab_convert_tree()
432 spin_lock_irqsave(&s->lock, flags); in sidtab_convert()
435 if (s->convert) { in sidtab_convert()
436 spin_unlock_irqrestore(&s->lock, flags); in sidtab_convert()
437 return -EBUSY; in sidtab_convert()
440 count = s->count; in sidtab_convert()
444 * live convert) in sidtab_convert()
446 rc = sidtab_do_lookup(params->target, count - 1, 1) ? 0 : -ENOMEM; in sidtab_convert()
448 spin_unlock_irqrestore(&s->lock, flags); in sidtab_convert()
453 params->target->count = count; in sidtab_convert()
455 /* enable live convert of new entries */ in sidtab_convert()
456 s->convert = params; in sidtab_convert()
459 spin_unlock_irqrestore(&s->lock, flags); in sidtab_convert()
463 /* convert all entries not covered by live convert */ in sidtab_convert()
465 rc = sidtab_convert_tree(¶ms->target->roots[level], in sidtab_convert()
466 &s->roots[level], &pos, count, level, params); in sidtab_convert()
468 /* we need to keep the old table - disable live convert */ in sidtab_convert()
469 spin_lock_irqsave(&s->lock, flags); in sidtab_convert()
470 s->convert = NULL; in sidtab_convert()
471 spin_unlock_irqrestore(&s->lock, flags); in sidtab_convert()
476 * so we must re-acquire the lock here. in sidtab_convert()
478 spin_lock_irqsave(&s->lock, flags); in sidtab_convert()
479 sidtab_convert_hashtable(params->target, count); in sidtab_convert()
480 spin_unlock_irqrestore(&s->lock, flags); in sidtab_convert()
489 /* cancelling policy load - disable live convert of sidtab */ in sidtab_cancel_convert()
490 spin_lock_irqsave(&s->lock, flags); in sidtab_cancel_convert()
491 s->convert = NULL; in sidtab_cancel_convert()
492 spin_unlock_irqrestore(&s->lock, flags); in sidtab_cancel_convert()
496 __acquires(&s->lock) in sidtab_freeze_begin()
498 spin_lock_irqsave(&s->lock, *flags); in sidtab_freeze_begin()
499 s->frozen = true; in sidtab_freeze_begin()
500 s->convert = NULL; in sidtab_freeze_begin()
503 __releases(&s->lock) in sidtab_freeze_end()
505 spin_unlock_irqrestore(&s->lock, *flags); in sidtab_freeze_end()
510 context_destroy(&entry->context); in sidtab_destroy_entry()
512 kfree(rcu_dereference_raw(entry->cache)); in sidtab_destroy_entry()
527 sidtab_destroy_tree(node->entries[i], level - 1); in sidtab_destroy_tree()
536 sidtab_destroy_entry(&node->entries[i]); in sidtab_destroy_tree()
546 if (s->isids[i].set) in sidtab_destroy()
547 sidtab_destroy_entry(&s->isids[i].entry); in sidtab_destroy()
550 while (level && !s->roots[level].ptr_inner) in sidtab_destroy()
551 --level; in sidtab_destroy()
553 sidtab_destroy_tree(s->roots[level], level); in sidtab_destroy()
570 if (entry->context.len) in sidtab_sid2str_put()
573 spin_lock_irqsave(&s->cache_lock, flags); in sidtab_sid2str_put()
575 cache = rcu_dereference_protected(entry->cache, in sidtab_sid2str_put()
576 lockdep_is_held(&s->cache_lock)); in sidtab_sid2str_put()
578 /* entry in cache - just bump to the head of LRU list */ in sidtab_sid2str_put()
579 list_move(&cache->lru_member, &s->cache_lru_list); in sidtab_sid2str_put()
587 if (s->cache_free_slots == 0) { in sidtab_sid2str_put()
588 /* pop a cache entry from the tail and free it */ in sidtab_sid2str_put()
589 victim = container_of(s->cache_lru_list.prev, in sidtab_sid2str_put()
591 list_del(&victim->lru_member); in sidtab_sid2str_put()
592 rcu_assign_pointer(victim->parent->cache, NULL); in sidtab_sid2str_put()
594 s->cache_free_slots--; in sidtab_sid2str_put()
596 cache->parent = entry; in sidtab_sid2str_put()
597 cache->len = str_len; in sidtab_sid2str_put()
598 memcpy(cache->str, str, str_len); in sidtab_sid2str_put()
599 list_add(&cache->lru_member, &s->cache_lru_list); in sidtab_sid2str_put()
601 rcu_assign_pointer(entry->cache, cache); in sidtab_sid2str_put()
604 spin_unlock_irqrestore(&s->cache_lock, flags); in sidtab_sid2str_put()
614 if (entry->context.len) in sidtab_sid2str_get()
615 return -ENOENT; /* do not cache invalid contexts */ in sidtab_sid2str_get()
619 cache = rcu_dereference(entry->cache); in sidtab_sid2str_get()
621 rc = -ENOENT; in sidtab_sid2str_get()
623 *out_len = cache->len; in sidtab_sid2str_get()
625 *out = kmemdup(cache->str, cache->len, GFP_ATOMIC); in sidtab_sid2str_get()
627 rc = -ENOMEM; in sidtab_sid2str_get()