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.
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.
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")
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.
{"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.