Course outline

Linux Security / Intermediate: service, policy, and lifecycle boundaries / Lesson 8

Distinguish mandatory policy from discretionary access

Use AppArmor as an identified reference while keeping profile attachment, mode, and effective denial separate.

About 4 min readContent reviewed
On this page

Lesson goals

  • Explain why DAC allow does not override a mandatory-policy denial.
  • Distinguish a profile file, loaded profile, attachment, and mode.

Keep complementary policy decisions separate

Discretionary access permits an operation under identity and object rules, while a mandatory policy can impose additional constraints. A file being writable by a service uid does not force AppArmor to allow the serviceโ€™s action. Conversely, a policy allow does not supply missing DAC permission. Ubuntuโ€™s AppArmor documentation is the selected distribution reference; this course does not load or inspect a profile. Other Linux security modules use different models and policy semantics. Do not translate one profile syntax into another by analogy or declare a host protected because a policy package exists.

Model a specific denial without changing the host

The first program intersects declared DAC and mandatory-policy decisions for a fictional read. It preserves an unknown policy result as unverified rather than granting access. This is a teaching relation over reviewed facts, not an AppArmor evaluator or complete kernel algorithm. Actual enforcement also depends on profile attachment, transitions, path interpretation, and other relevant controls. The positive case matters: a model that denies everything could appear safe while preventing the report worker from reading public inputs. Keep the policy requirement and actual runtime mechanism distinct.

python Keep discretionary, mandatory, and unknown outcomes visible
def reviewed_read(dac, mandatory):
    if dac is not True:
        return "DENIED_DAC"
    if mandatory is None:
        return "UNVERIFIED_POLICY"
    return "ALLOWED" if mandatory is True else "DENIED_POLICY"

assert reviewed_read(True, True) == "ALLOWED"
assert reviewed_read(True, False) == "DENIED_POLICY"
assert reviewed_read(False, True) == "DENIED_DAC"
assert reviewed_read(True, None) == "UNVERIFIED_POLICY"
print("four declared DAC and mandatory-policy outcomes checked")
Expected output
four declared DAC and mandatory-policy outcomes checked

The complete program evaluates four invented facts locally. It performs no kernel access check, file operation, profile load, or policy probe. The error markers are classroom categories, not actual AppArmor log messages.

Review profile presence, attachment, and mode

A profile file on disk, a loaded profile, and a process actually confined by that profile are different states. Enforce and complain modes also answer different questions. Complain mode generally logs policy violations rather than enforcing ordinary denials, but explicit deny rules have documented exceptions and remain significant. It is therefore unsafe to reduce mode semantics to a universal allow-all boolean. The second record retains unknown attachment and mode. It is non-runnable data, not AppArmor syntax, and does not establish any actual policy state. A real diagnosis must obtain approved evidence of the specific process and loaded policy.

json A profile-state review record with unresolved enforcement
{"profile":"report-worker-lab","fileReviewed":true,"loadedVerified":false,"processAttachment":"unknown","mode":"unknown","ordinaryDenyTested":false,"explicitDenyRulesReviewed":false,"hostPolicyChanged":false}

The non-runnable JSON is custom classroom metadata and configures no profile. A true fileReviewed value is not evidence that a process is confined. Unknown attachment and mode must remain visible in any conclusion.

Repair the relevant rule rather than disabling the layer

A legitimate refusal can result from an incorrect path assumption, missing required resource, unexpected transition, wrong profile, or a real forbidden operation. Use approved existing diagnostics and owned fixtures to distinguish them. Do not disable AppArmor globally or broaden every path merely to make a service start. Preserve the exact operation, process context, profile revision, and nonsecret denial category. A narrow policy change needs review of the workload and adjacent denials. This course supplies no policy-management commands and sends no probes to a running application or host.

Verify intended allow and deny behavior under the selected policy

In a separately authorized disposable environment, verify required input/output work and a benign forbidden-resource case under the actual loaded profile and mode. Check DAC and service-view conditions too, so the observed denial is attributed to the correct layer. Record platform and policy assumptions and any unexecuted transitions. The local model and review record establish only reasoning about declared states. They do not prove that AppArmor, another LSM, or this host enforces a particular rule. Precise evidence avoids replacing a useful defense with a broad bypass based on an unexplained error.

Common errors and fixes

DAC write permission overrides mandatory denial

Why it happens
Complementary access layers are treated as alternatives.
How to fix it
Review both decisions and the actual attached policy.
Prevent it next time
Test the denial source explicitly.

A profile file proves process confinement

Why it happens
Loaded state, attachment, and mode are unverified.
How to fix it
Record each state and obtain approved runtime evidence.
Prevent it next time
Keep unknowns separate from compliance.

Every refusal disables the whole policy layer

Why it happens
The failed operation and rule are not localized.
How to fix it
Diagnose the narrow mismatch and preserve unrelated denials.
Prevent it next time
Review positive and negative regressions for policy changes.

Check your understanding

1. The file is reviewed but attachment is unknown. Can the worker be called confined?

Show worked solution

No. Report design review evidence and pending loaded/attachment/mode verification separately. A file can exist without governing the process. The classroom record deliberately preserves that gap and performs no host policy inspection or change.

2. Why is complain not modeled as a universal allow-all switch?

Show worked solution

Ordinary complaint behavior and explicit deny-rule semantics differ, while DAC and other layers still apply. Read the selected policy documentation and verify actual mode and rules in an authorized environment. Do not infer successful access from one mode label or weaken the entire host policy to diagnose a specific operation.

Key takeaways

  • Mandatory policy can add restrictions beyond DAC.
  • Profile presence, loaded state, attachment, and mode differ.
  • Narrow diagnosis preserves useful allow and deny behavior.

Official references