security/apparmor/match.c

Source file repositories/reference/linux-study-clean/security/apparmor/match.c

File Facts

System
Linux kernel
Corpus path
security/apparmor/match.c
Extension
.c
Size
21346 bytes
Lines
829
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 (DEFAULT_TABLE(dfa)[i] >= state_count) {
			pr_err("AppArmor DFA default state out of bounds");
			goto out;
		}
		if (BASE_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) {
			pr_err("AppArmor DFA state with invalid match flags");
			goto out;
		}
		if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE)) {
			if (!(dfa->flags & YYTH_FLAG_DIFF_ENCODE)) {
				pr_err("AppArmor DFA diff encoded transition state without header flag");
				goto out;
			}
		}
		if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_OOB_TRANSITION)) {
			if (base_idx(BASE_TABLE(dfa)[i]) < dfa->max_oob) {
				pr_err("AppArmor DFA out of bad transition out of range");
				goto out;
			}
			if (!(dfa->flags & YYTH_FLAG_OOB_TRANS)) {
				pr_err("AppArmor DFA out of bad transition state without header flag");
				goto out;
			}
		}
		if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
			pr_err("AppArmor DFA next/check upper bounds error\n");
			goto out;
		}
	}

	for (i = 0; i < trans_count; i++) {
		if (NEXT_TABLE(dfa)[i] >= state_count)
			goto out;
		if (CHECK_TABLE(dfa)[i] >= state_count)
			goto out;
	}

	/* Now that all the other tables are verified, verify diffencoding */
	for (i = 0; i < state_count; i++) {
		size_t j, k;

		for (j = i;
		     ((BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
		      !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE_VERIFIED));
		     j = k) {
			if (BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE)
				/* loop in current chain */
				goto out;
			k = DEFAULT_TABLE(dfa)[j];
			if (j == k)
				/* self loop */
				goto out;
			BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
		}
		/* move mark to verified */
		for (j = i;
		     (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE);
		     j = k) {
			k = DEFAULT_TABLE(dfa)[j];
			if (j < i)
				/* jumps to state/chain that has been
				 * verified
				 */
				break;
			BASE_TABLE(dfa)[j] &= ~MARK_DIFF_ENCODE;
			BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE_VERIFIED;
		}
	}
	error = 0;

out:
	return error;
}

/**
 * dfa_free - free a dfa allocated by aa_dfa_unpack
 * @dfa: the dfa to free  (MAYBE NULL)
 *
 * Requires: reference count to dfa == 0
 */
static void dfa_free(struct aa_dfa *dfa)
{
	if (dfa) {
		int i;

		for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
			kvfree(dfa->tables[i]);
			dfa->tables[i] = NULL;
		}
		kfree(dfa);

Annotation

Implementation Notes