security/selinux/ss/sidtab.c

Source file repositories/reference/linux-study-clean/security/selinux/ss/sidtab.c

File Facts

System
Linux kernel
Corpus path
security/selinux/ss/sidtab.c
Extension
.c
Size
14688 bytes
Lines
639
Domain
Core OS
Bucket
Security And Isolation
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sidtab_str_cache {
	struct rcu_head rcu_member;
	struct list_head lru_member;
	struct sidtab_entry *parent;
	u32 len;
	char str[] __counted_by(len);
};

#define index_to_sid(index) ((index) + SECINITSID_NUM + 1)
#define sid_to_index(sid)   ((sid) - (SECINITSID_NUM + 1))

int sidtab_init(struct sidtab *s)
{
	u32 i;

	memset(s->roots, 0, sizeof(s->roots));

	for (i = 0; i < SECINITSID_NUM; i++)
		s->isids[i].set = 0;

	s->frozen = false;
	s->count = 0;
	s->convert = NULL;
	hash_init(s->context_to_sid);

	spin_lock_init(&s->lock);

#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
	s->cache_free_slots = CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE;
	INIT_LIST_HEAD(&s->cache_lru_list);
	spin_lock_init(&s->cache_lock);
#endif

	return 0;
}

static u32 context_to_sid(struct sidtab *s, struct context *context, u32 hash)
{
	struct sidtab_entry *entry;
	u32 sid = 0;

	rcu_read_lock();
	hash_for_each_possible_rcu(s->context_to_sid, entry, list, hash) {
		if (entry->hash != hash)
			continue;
		if (context_equal(&entry->context, context)) {
			sid = entry->sid;
			break;
		}
	}
	rcu_read_unlock();
	return sid;
}

int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context)
{
	struct sidtab_isid_entry *isid;
	u32 hash;
	int rc;

	if (sid == 0 || sid > SECINITSID_NUM)
		return -EINVAL;

	isid = &s->isids[sid - 1];

	rc = context_cpy(&isid->entry.context, context);
	if (rc)
		return rc;

#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
	isid->entry.cache = NULL;
#endif
	isid->set = 1;

	hash = context_compute_hash(context);

	/*
	 * Multiple initial sids may map to the same context. Check that this
	 * context is not already represented in the context_to_sid hashtable
	 * to avoid duplicate entries and long linked lists upon hash
	 * collision.
	 */
	if (!context_to_sid(s, context, hash)) {
		isid->entry.sid = sid;
		isid->entry.hash = hash;
		hash_add(s->context_to_sid, &isid->entry.list, hash);
	}

	return 0;
}

Annotation

Implementation Notes