security/selinux/ss/avtab.c

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

File Facts

System
Linux kernel
Corpus path
security/selinux/ss/avtab.c
Extension
.c
Size
15415 bytes
Lines
619
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

if (xperms == NULL) {
			kmem_cache_free(avtab_node_cachep, newnode);
			return NULL;
		}
		*xperms = *(datum->u.xperms);
		newnode->datum.u.xperms = xperms;
	} else {
		newnode->datum.u.data = datum->u.data;
	}

	newnode->next = *dst;
	*dst = newnode;

	h->nel++;
	return newnode;
}

static int avtab_node_cmp(const struct avtab_key *key1,
			  const struct avtab_key *key2)
{
	u16 specified = key1->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);

	if (key1->source_type == key2->source_type &&
	    key1->target_type == key2->target_type &&
	    key1->target_class == key2->target_class &&
	    (specified & key2->specified))
		return 0;
	if (key1->source_type < key2->source_type)
		return -1;
	if (key1->source_type == key2->source_type &&
	    key1->target_type < key2->target_type)
		return -1;
	if (key1->source_type == key2->source_type &&
	    key1->target_type == key2->target_type &&
	    key1->target_class < key2->target_class)
		return -1;
	return 1;
}

static int avtab_insert(struct avtab *h, const struct avtab_key *key,
			const struct avtab_datum *datum)
{
	u32 hvalue;
	struct avtab_node *prev, *cur, *newnode;
	int cmp;

	if (!h || !h->nslot || h->nel == U32_MAX)
		return -EINVAL;

	hvalue = avtab_hash(key, h->mask);
	for (prev = NULL, cur = h->htable[hvalue]; cur;
	     prev = cur, cur = cur->next) {
		cmp = avtab_node_cmp(key, &cur->key);
		/* extended perms may not be unique */
		if (cmp == 0 && !(key->specified & AVTAB_XPERMS))
			return -EEXIST;
		if (cmp <= 0)
			break;
	}

	newnode = avtab_insert_node(h, prev ? &prev->next : &h->htable[hvalue],
				    key, datum);
	if (!newnode)
		return -ENOMEM;

	return 0;
}

/* Unlike avtab_insert(), this function allow multiple insertions of the same
 * key/specified mask into the table, as needed by the conditional avtab.
 * It also returns a pointer to the node inserted.
 */
struct avtab_node *avtab_insert_nonunique(struct avtab *h,
					  const struct avtab_key *key,
					  const struct avtab_datum *datum)
{
	u32 hvalue;
	struct avtab_node *prev, *cur;
	int cmp;

	if (!h || !h->nslot || h->nel == U32_MAX)
		return NULL;
	hvalue = avtab_hash(key, h->mask);
	for (prev = NULL, cur = h->htable[hvalue]; cur;
	     prev = cur, cur = cur->next) {
		cmp = avtab_node_cmp(key, &cur->key);
		if (cmp <= 0)
			break;
	}
	return avtab_insert_node(h, prev ? &prev->next : &h->htable[hvalue],

Annotation

Implementation Notes