Project 2: AVC Denial Analyzer & Auto-Fixer

Build a CLI that parses AVC denials, groups them into root causes, and proposes the safest remediation path.

Quick Reference

Attribute Value
Difficulty Level 2: Intermediate
Time Estimate 1-2 weeks
Main Programming Language Python (Alternatives: Go, Rust)
Alternative Programming Languages Go, Rust
Coolness Level Level 3
Business Potential 2
Prerequisites Project 1, audit log basics, SELinux tools installed
Key Topics AVC parsing, audit pipeline, policy reasoning, safe remediation logic

1. Learning Objectives

By completing this project, you will:

  1. Parse AVC log messages into structured, queryable data.
  2. Map AVC fields to policy rule shapes and identify likely fixes.
  3. Build a remediation decision tree that prefers labeling and booleans over broad allow rules.
  4. Generate deterministic reports with evidence for each recommendation.
  5. Understand audit log flow and how SELinux denials are recorded.

2. All Theory Needed (Per-Concept Breakdown)

AVC Messages and the Linux Audit Pipeline

Fundamentals

AVC denials are produced by SELinux when access is blocked by policy. They are recorded by the Linux audit subsystem as structured log records containing the subject context (scontext), target context (tcontext), class (tclass), permissions (perms), and process metadata (PID, command, path, inode). These records are the primary evidence source for troubleshooting. To build an analyzer, you must understand how audit logs are generated, where they are stored, and how to parse them reliably. The audit pipeline adds timestamps and event IDs, and sometimes splits a single denial into multiple log entries. Your tool must normalize these records into a canonical data model so that repeated denials can be grouped and root causes identified.

Deep Dive into the concept

The audit subsystem is a kernel feature that records security-relevant events, including SELinux decisions. When an SELinux denial occurs, the LSM hook returns an error and reports an AVC message. The audit layer packages that message into a record line in /var/log/audit/audit.log (or via journalctl on some systems). The canonical format looks like: type=AVC msg=audit(1700000000.123:456): avc: denied { write } for pid=2451 comm="myapp" scontext=... tcontext=... tclass=dir. Key fields are critical: scontext and tcontext identify the types involved; tclass defines the object class; perms define the requested access; comm provides the process name. The event ID after the colon is a unique audit sequence number, which lets you correlate related records like PATH or CWD entries. This is important because not all information is on the main line. A denial involving a path may include additional PATH records in the same event, so a reliable parser must group records by event ID.

AVC denials are not the same as kernel permission errors from DAC. They are layered on top of DAC and can produce EACCES even when DAC would allow access. This is why your tool should label denials explicitly as SELinux decisions. Audit data also differs between distros and kernel versions. For example, some systems include permissive=1 indicating that the access was allowed because the domain is permissive. Your analyzer should treat permissive denials as warnings rather than failures, because they indicate policy gaps that would break under enforcement.

Parsing is non-trivial because the audit log is line-oriented and key order can vary. Relying on regex alone is brittle; a robust parser should tokenize key=value pairs and handle quoted values. Another nuance is that multiple permissions can be present in a single denial, e.g., { read write }. Your data model should store them as a set. This matters for grouping, because a denial for read and write on the same object should be grouped together if the root cause is the same labeling error.

Understanding the audit pipeline also teaches you the limits of inference. A denial can be caused by mislabeling, a missing allow rule, or a policy boolean being off. The audit log does not always tell you which; it only tells you what was denied. Your tool must therefore combine audit evidence with policy knowledge. For example, if the target path is /var/www and the tcontext is httpd_sys_content_t but the permission is write, the likely fix is to relabel to httpd_sys_rw_content_t rather than to add a new allow rule. But to make that decision you must identify the object type and understand its semantics. That is why the audit pipeline concept is the foundation for everything else in this project.

Additional operational notes on AVC Messages and the Linux Audit Pipeline: In real systems, this concept interacts with policy versions, distribution defaults, and local overrides. Always record the exact policy version and runtime toggles when diagnosing behavior, because the same action can be allowed on one host and denied on another. When you change configuration related to this concept, capture before/after evidence (labels, logs, and outcomes) so you can justify the change, detect regressions, and roll it back if needed. Treat every tweak as a hypothesis: change one variable, re-run the same action, and compare results against a known baseline. This makes debugging repeatable and keeps your fixes defensible.

From a design perspective, treat AVC Messages and the Linux Audit Pipeline as an invariant: define what success means, which data proves it, and what failure looks like. Build tooling that supports dry-run mode and deterministic fixtures so you can validate behavior without risking production. This also makes the concept teachable to others. Finally, connect the concept to security and performance trade-offs: overly broad changes reduce security signal, while overly strict changes create operational friction. Good designs surface these trade-offs explicitly so operators can make safe decisions.

How this fit on projects

AVC parsing is used in §3.2, §3.7, and the remediation rules in §5.10 Phase 2. It is also reused in P12-enterprise-selinux-security-platform.md for fleet-scale analysis.

Definitions & key terms

  • AVC -> Access Vector Cache denial record
  • audit event ID -> unique sequence number for related records
  • scontext/tcontext -> subject and target security contexts
  • permissive=1 -> denial logged but access allowed

Mental model diagram

syscall -> LSM hook -> SELinux deny -> audit record -> /var/log/audit/audit.log

How it works (step-by-step, with invariants and failure modes)

  1. Kernel triggers an LSM hook for an operation.
  2. SELinux policy denies the operation.
  3. An AVC message is emitted and recorded by audit.
  4. Audit writes the record with a timestamp and event ID.
  5. User space tools (ausearch, aureport) parse and present it.

Invariants: each AVC has scontext, tcontext, class, perms. Failure modes: auditd stopped, logs rotated, or permissions prevent reading audit logs.

Minimal concrete example

$ ausearch -m avc -ts recent | head -1

Common misconceptions

  • “AVC denials only happen in enforcing mode.” -> They also appear in permissive mode.
  • “One line equals one denial.” -> A denial can include multiple records per event.

Check-your-understanding questions

  1. Why should you group audit records by event ID?
  2. What does permissive=1 imply?
  3. Which fields define the policy decision input?

Check-your-understanding answers

  1. Related records (PATH, CWD) share an event ID and provide extra context.
  2. The denial was logged but access was allowed due to permissive domain or mode.
  3. scontext, tcontext, tclass, and perms.

Real-world applications

  • Security operations teams triage denials during deployments.
  • Compliance reporting for least privilege enforcement.

Where you’ll apply it

References

  • Red Hat SELinux Guide, troubleshooting chapter
  • “The Linux Programming Interface” (Kerrisk), audit subsystem

Key insights

AVC denials are structured policy evidence; treat them as data, not as opaque errors.

Summary

AVC messages are produced by SELinux via the audit pipeline and contain the fields needed to reason about policy decisions.

Homework/Exercises to practice the concept

  1. Trigger a denial and locate its event ID in audit.log.
  2. Use ausearch -m avc -ts recent and extract scontext/tcontext.
  3. Find an AVC with permissive=1 and explain the implication.

Solutions to the homework/exercises

  1. Use audit.log to locate audit(....:ID) and match the ID to PATH records.
  2. ausearch output includes the fields directly; copy them into a table.
  3. The system logged the denial but did not enforce it due to permissive mode.

Remediation Taxonomy: Label, Boolean, or Policy

Fundamentals

SELinux denials can usually be resolved in one of three ways: fix labeling, enable a boolean, or write a policy rule. Labeling fixes are preferred because they align objects with existing policy; booleans are second because they toggle vetted policy paths; custom policy rules are last because they expand permissions. A correct analyzer should recommend the least risky remediation based on evidence from the AVC and the expected label rules. This concept is the heart of the auto-fixer: classify the denial by root cause and propose the safest action.

Deep Dive into the concept

A denial is not a request to “allow everything”; it is a signal that policy does not permit a specific access between a source and target. The safest fix is to align the target object with the type the policy already expects. For example, if httpd_t is denied write access to httpd_sys_content_t, the fix is often to label the directory as httpd_sys_rw_content_t, because policy already allows that type. This is a labeling fix, not a policy change. The next safest option is to enable a boolean. Booleans are policy-encoded switches that gate optional functionality, such as allowing httpd_t to connect to the network. These are designed for operational flexibility, and when a denial matches a known boolean (e.g., httpd_can_network_connect), enabling it is safer than creating a custom allow rule because it preserves the policy authors’ intent.

Policy module changes are the last resort. They can be necessary for custom applications, but they must be narrow and justified. An analyzer should avoid producing broad allow rules that ignore object types or permissions. For example, allow myapp_t var_log_t:file { read write } is less precise than labeling logs as myapp_log_t and granting that specific access. A robust remediation decision tree should evaluate: (1) is the target path mislabeled relative to policy? (2) does a boolean exist that would allow this access? (3) if neither, can we generate a minimal policy module with specific types and permissions? The tool can use semanage fcontext -l and getsebool -a to answer the first two questions, and only then generate a suggested allow rule. This prevents the common anti-pattern of blindly running audit2allow -a.

In practice, you need heuristics to map AVCs to labeling fixes. If the target path is within a well-known directory (like /var/www) but has a default_t label, drift is likely. If the target type is a read-only content type and the permission requested is write, then the policy is intentionally strict and you must move the object to a writable type. For booleans, the existence of a boolean that mentions the source domain (e.g., httpd_) is a strong signal. But booleans sometimes cover multiple domains, so your tool should query sepolicy booleans to retrieve descriptions and match them to the AVC context. The result should be a ranked recommendation with evidence.

This taxonomy also implies that your tool must record why it chose a fix. The report should include the path, current label, expected label, and the boolean description if applicable. This creates trust and encourages operators to apply the fix instead of disabling SELinux. The tool should also support a dry-run mode that prints commands without executing them. This aligns with operational safety: remediation suggestions must be reviewable.

Operational expansion for Remediation Taxonomy: Label, Boolean, or Policy: In real systems, the behavior you observe is the product of policy, labels, and runtime state. That means your investigation workflow must be repeatable. Start by documenting the exact inputs (contexts, paths, users, domains, ports, and the action attempted) and the exact outputs (audit events, error codes, and any policy query results). Then, replay the same action after each change so you can attribute cause and effect. When the concept touches multiple subsystems, isolate variables: change one label, one boolean, or one rule at a time. This reduces confusion and prevents accidental privilege creep. Use staging environments or fixtures to test fixes before deploying them widely, and always keep a rollback path ready.

To deepen understanding, connect Remediation Taxonomy: Label, Boolean, or Policy to adjacent concepts: how it affects policy decisions, how it appears in logs, and how it changes operational risk. Build small verification scripts that assert the expected outcome and fail loudly if the outcome diverges. Over time, these scripts become a regression suite for your SELinux posture. Finally, treat the concept as documentation-worthy: write down the invariants it guarantees, the constraints it imposes, and the exact evidence that proves it works. This makes future debugging faster and creates a shared mental model for teams.

How this fit on projects

AVC parsing is used in §3.2, §3.7, and the remediation rules in §5.10 Phase 2. It is also reused in P12-enterprise-selinux-security-platform.md for fleet-scale analysis.

Definitions & key terms

  • AVC -> Access Vector Cache denial record
  • audit event ID -> unique sequence number for related records
  • scontext/tcontext -> subject and target security contexts
  • permissive=1 -> denial logged but access allowed

Mental model diagram

syscall -> LSM hook -> SELinux deny -> audit record -> /var/log/audit/audit.log

How it works (step-by-step, with invariants and failure modes)

  1. Kernel triggers an LSM hook for an operation.
  2. SELinux policy denies the operation.
  3. An AVC message is emitted and recorded by audit.
  4. Audit writes the record with a timestamp and event ID.
  5. User space tools (ausearch, aureport) parse and present it.

Invariants: each AVC has scontext, tcontext, class, perms. Failure modes: auditd stopped, logs rotated, or permissions prevent reading audit logs.

Minimal concrete example

$ ausearch -m avc -ts recent | head -1

Common misconceptions

  • “AVC denials only happen in enforcing mode.” -> They also appear in permissive mode.
  • “One line equals one denial.” -> A denial can include multiple records per event.

Check-your-understanding questions

  1. Why should you group audit records by event ID?
  2. What does permissive=1 imply?
  3. Which fields define the policy decision input?

Check-your-understanding answers

  1. Related records (PATH, CWD) share an event ID and provide extra context.
  2. The denial was logged but access was allowed due to permissive domain or mode.
  3. scontext, tcontext, tclass, and perms.

Real-world applications

  • Security operations teams triage denials during deployments.
  • Compliance reporting for least privilege enforcement.

Where you’ll apply it

References

  • Red Hat SELinux Guide, troubleshooting chapter
  • “The Linux Programming Interface” (Kerrisk), audit subsystem

Key insights

AVC denials are structured policy evidence; treat them as data, not as opaque errors.

Summary

AVC messages are produced by SELinux via the audit pipeline and contain the fields needed to reason about policy decisions.

Homework/Exercises to practice the concept

  1. Trigger a denial and locate its event ID in audit.log.
  2. Use ausearch -m avc -ts recent and extract scontext/tcontext.
  3. Find an AVC with permissive=1 and explain the implication.

Solutions to the homework/exercises

  1. Use audit.log to locate audit(....:ID) and match the ID to PATH records.
  2. ausearch output includes the fields directly; copy them into a table.
  3. The system logged the denial but did not enforce it due to permissive mode.

Mapping AVCs to Policy Rules and Risk

Fundamentals

An AVC denial is a policy decision. The rule that would allow it has a specific shape: allow <s_type> <t_type>:<class> { perms };. By extracting scontext, tcontext, tclass, and perms, you can form a minimal allow rule. This is essential when a custom policy is required. However, not all allow rules are equal: some weaken security more than others. Your tool must understand risk: adding permissions to high-privilege domains or to sensitive target types is riskier than adding permissions to a constrained domain for a specific log directory. This concept teaches how to reason about the impact of a policy change.

Deep Dive into the concept

SELinux policy language is declarative. Allow rules grant access; neverallow rules forbid access even if allow rules exist; and type enforcement constraints can further restrict access. When you map an AVC to an allow rule, you are proposing a change that may or may not be compatible with existing policy. For example, if the AVC refers to shadow_t, there may be a neverallow preventing any domain except a small set from reading it. Your tool should detect such cases or at least flag them as high risk. You can use sesearch -A or seinfo to check whether similar rules already exist. If a rule does not exist but a boolean controls it, then enabling the boolean is safer than creating a custom rule.

Risk assessment also depends on the domains involved. Allowing a confined domain (myapp_t) to read its own config file is low risk. Allowing unconfined_t to write to system files is high risk but also unnecessary because unconfined already bypasses most restrictions. Another dimension is class and permission. read on a file is often lower risk than write or execute. For directories, add_name or remove_name can modify the filesystem structure and are higher risk. Your tool should assign a risk score based on these factors and display it in the report. This guides human review and makes the tool usable in operations.

When generating policy suggestions, your analyzer should be explicit that it is only a suggestion. It should write a .te file with the minimal rule and instruct the user to review and compile with checkmodule and semodule. This reinforces good practice. To keep things safe, your tool can include a guard: if the target type is in a sensitive list (shadow_t, passwd_t, security_t), it should refuse to generate a rule and require manual review. This is a prudent engineering choice.

Another subtlety is that AVCs can include the same denial multiple times because of repeated attempts. Grouping denials by (s_type, t_type, class, perms) is therefore a natural way to deduplicate and estimate risk. This also helps create a stable output even when logs are noisy. Determinism matters for tests: given the same input logs, the tool should output the same grouped denials and risk scores.

Operational expansion for f the denial involves httpd_t connecting to a network socket, the boolean is relevant.: In real systems, the behavior you observe is the product of policy, labels, and runtime state. That means your investigation workflow must be repeatable. Start by documenting the exact inputs (contexts, paths, users, domains, ports, and the action attempted) and the exact outputs (audit events, error codes, and any policy query results). Then, replay the same action after each change so you can attribute cause and effect. When the concept touches multiple subsystems, isolate variables: change one label, one boolean, or one rule at a time. This reduces confusion and prevents accidental privilege creep. Use staging environments or fixtures to test fixes before deploying them widely, and always keep a rollback path ready.

To deepen understanding, connect f the denial involves httpd_t connecting to a network socket, the boolean is relevant. to adjacent concepts: how it affects policy decisions, how it appears in logs, and how it changes operational risk. Build small verification scripts that assert the expected outcome and fail loudly if the outcome diverges. Over time, these scripts become a regression suite for your SELinux posture. Finally, treat the concept as documentation-worthy: write down the invariants it guarantees, the constraints it imposes, and the exact evidence that proves it works. This makes future debugging faster and creates a shared mental model for teams.

How this fit on projects

This concept drives §3.2 Functional Requirements and §3.7 Real World Outcome. It is also required in P09-ansible-selinux-hardening-role.md for automated remediation decisions.

Further depth on Mapping AVCs to Policy Rules and Risk: In production environments, this concept is shaped by policy versions, automation layers, and distro-specific defaults. To keep reasoning consistent, capture a minimal evidence bundle every time you analyze behavior: the policy name/version, the exact labels or contexts involved, the command that triggered the action, and the resulting audit event. If the same action yields different decisions on two hosts, treat that as a signal that a hidden variable changed (boolean state, module priority, label drift, or category range). This disciplined approach prevents trial-and-error debugging and makes your conclusions defensible.

Operationally, build a short checklist for Mapping AVCs to Policy Rules and Risk: verify prerequisites, verify labels or mappings, verify policy query results, then run the action and confirm the expected audit outcome. Track metrics that reflect stability, such as the count of denials per hour, the number of unique denial keys, or the fraction of hosts in compliance. When you must change behavior, apply the smallest change that can be verified (label fix before boolean, boolean before policy). Document the rollback path and include a post-change validation step so the system returns to a known-good state.

Definitions & key terms

  • labeling fix -> align file labels with policy expectations
  • boolean -> policy toggle that gates optional permissions
  • custom policy -> additional allow rules for specific domains
  • least privilege -> grant the minimum required permissions

Mental model diagram

AVC denial -> classify root cause ->
  [label drift] | [boolean exists] | [policy gap]

How it works (step-by-step, with invariants and failure modes)

  1. Parse AVC and extract path, scontext, tcontext, class, perms.
  2. Check expected label for the path.
  3. If expected label differs, recommend relabeling.
  4. Else search booleans that mention the source domain or target type.
  5. If a boolean matches, recommend enabling it.
  6. Otherwise generate a minimal allow-rule suggestion.

Invariants: labeling fixes are always safer than policy expansion. Failure modes: incorrect path parsing, missing boolean metadata, or unsafe allow rules.

Minimal concrete example

# Label fix suggestion
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/uploads(/.*)?"
restorecon -Rv /var/www/uploads

Common misconceptions

  • “audit2allow is always the answer.” -> It can be overly broad.
  • “If a boolean exists, it is always safe to enable.” -> Some booleans are risky and should be reviewed.

Check-your-understanding questions

  1. Why is relabeling preferred over adding allow rules?
  2. When would a boolean be the safest fix?
  3. What evidence should accompany a policy module suggestion?

Check-your-understanding answers

  1. Relabeling uses existing policy intent without expanding permissions.
  2. When a known boolean explicitly gates the denied access.
  3. The exact AVC fields, the minimal rule shape, and why labeling/booleans do not apply.

Real-world applications

  • SRE teams resolving denials during deployments.
  • Compliance workflows that require evidence-based fixes.

Where you’ll apply it

References

  • “SELinux System Administration” (Vermeulen), troubleshooting chapters
  • “SELinux by Example” (Mayer et al.), policy design

Key insights

Safe remediation is about aligning objects with policy intent, not weakening the policy.

Summary

A remediation taxonomy helps you choose the safest fix: labeling first, booleans second, custom policy last.

Homework/Exercises to practice the concept

  1. Find an AVC caused by default_t and propose a labeling fix.
  2. Identify a denial that maps to httpd_can_network_connect and explain why.
  3. Draft a minimal allow rule for a custom domain and explain its scope.

Solutions to the homework/exercises

  1. Use matchpathcon to determine the expected label and apply restorecon.
  2. If the denial involves httpd_t connecting to a network socket, the boolean is relevant.
  3. The rule should name the specific types and permissions observed in the AVC.

3. Project Specification

3.1 What You Will Build

A CLI tool named avcfix that ingests AVC denials, groups them into root causes, and outputs a remediation report with safe recommendations and optional policy module skeletons.

Included features:

  • Parse audit logs (file or stdin)
  • Group denials by (s_type, t_type, class, perms, path)
  • Identify likely labeling fixes
  • Detect relevant booleans
  • Generate minimal .te rule suggestions

Excluded features:

  • Automatic policy installation
  • Auto-apply changes without review
  • Full audit log management

3.2 Functional Requirements

  1. Log Ingestion: Read from audit.log or stdin with a --since filter.
  2. Parsing: Normalize AVCs into structured fields and group by root cause.
  3. Label Checks: Compare paths against expected labels using matchpathcon.
  4. Boolean Checks: Search available booleans and include descriptions.
  5. Recommendation Engine: Rank fixes (label, boolean, policy) with evidence.
  6. Output: Render a human-readable report and JSON output.

3.3 Non-Functional Requirements

  • Performance: Parse 50k AVC lines in under 10 seconds.
  • Reliability: Handle rotated logs and missing PATH entries.
  • Usability: Recommendations must include exact commands and rationale.

3.4 Example Usage / Output

$ avcfix analyze --since "1h"

Found 12 AVC denials (3 root causes)

1) Label mismatch: /opt/myapp/logs
   current:  system_u:object_r:default_t:s0
   expected: system_u:object_r:var_log_t:s0
   Fix: semanage fcontext -a -t var_log_t "/opt/myapp/logs(/.*)?"
        restorecon -Rv /opt/myapp/logs

2) Boolean required: httpd_can_network_connect
   Fix: setsebool -P httpd_can_network_connect on

3) Policy gap: myapp_t -> var_run_t:dir { write add_name }
   Fix: generate minimal module (risk: medium)

3.5 Data Formats / Schemas / Protocols

JSON output schema (v1):

{
  "version": "1.0",
  "generated_at": "2026-01-01T00:00:00Z",
  "groups": [
    {
      "key": "myapp_t|var_run_t|dir|write,add_name",
      "count": 12,
      "path": "/var/run/myapp",
      "recommendation": "policy",
      "risk": "medium"
    }
  ]
}

3.6 Edge Cases

  • Missing PATH records for a denial
  • AVCs from permissive domains
  • Booleans that exist but are already enabled
  • Denials involving transient files under /tmp

3.7 Real World Outcome

3.7.1 How to Run (Copy/Paste)

./avcfix analyze --since "1h" --format text

3.7.2 Golden Path Demo (Deterministic)

Use fixture audit logs in fixtures/audit.log and freeze timestamps to 2026-01-01T00:00:00Z.

3.7.3 CLI Transcript (Success and Failure)

$ ./avcfix analyze --file fixtures/audit.log
Root causes: 3
Report written to ./report.txt
Exit code: 0

$ ./avcfix analyze --file /missing/log
ERROR: audit log not found
Exit code: 2

3.7.4 If CLI: exit codes

  • 0 success
  • 1 success with warnings (permissive denials only)
  • 2 input error or missing log
  • 3 audit tools missing

4. Solution Architecture

4.1 High-Level Design

+-----------+     +---------------------+     +----------------------+
| Log Input | --> | AVC Parser/Normalizer| --> | Root Cause Grouper   |
+-----------+     +---------------------+     +----------+-----------+
                                                     |
                                                     v
                                         +----------------------+
                                         | Recommendation Engine|
                                         +----------+-----------+
                                                     |
                                                     v
                                         +----------------------+
                                         | Report Renderer      |
                                         +----------------------+

4.2 Key Components

Component Responsibility Key Decisions
Parser Extract AVC fields and event IDs Tokenize key=value pairs
Grouper Group by root cause keys Stable ordering for determinism
Remediator Decide label vs boolean vs policy Prefer safe fixes
Renderer Output report and JSON Include evidence and commands

4.3 Data Structures (No Full Code)

DenialGroup = {
  "key": "s|t|class|perms",
  "paths": ["/path"],
  "count": 12,
  "recommendation": "label|boolean|policy",
  "risk": "low|medium|high"
}

4.4 Algorithm Overview

Key Algorithm: Recommendation Engine

  1. For each group, resolve expected label using matchpathcon.
  2. If mismatch, choose label fix.
  3. Else, search booleans with matching domains or descriptions.
  4. Else, generate minimal allow rule suggestion.

Complexity Analysis:

  • Time: O(n) AVCs + O(m) boolean queries
  • Space: O(n) for grouped denials

5. Implementation Guide

5.1 Development Environment Setup

sudo dnf install -y policycoreutils-python-utils setroubleshoot

5.2 Project Structure

avcfix/
├── avcfix/
│   ├── cli.py
│   ├── parse.py
│   ├── group.py
│   ├── remediate.py
│   └── report.py
├── fixtures/
└── tests/

5.3 The Core Question You’re Answering

“What is the minimal, safest fix for a given SELinux denial?”

5.4 Concepts You Must Understand First

  1. AVC fields and audit log structure.
  2. Labeling workflow and matchpathcon.
  3. Booleans and policy rule shape.

5.5 Questions to Guide Your Design

  1. How will you keep recommendations deterministic for tests?
  2. What evidence should accompany each recommendation?
  3. When should the tool refuse to suggest a policy change?

5.6 Thinking Exercise

Given three denials for the same path, design a grouping key that avoids double counting while preserving important differences.

5.7 The Interview Questions They’ll Ask

  1. “What fields are in an AVC denial?”
  2. “Why is relabeling safer than policy changes?”
  3. “What is a SELinux boolean?”

5.8 Hints in Layers

Hint 1: Start by parsing with key=value pairs

Hint 2: Add matchpathcon checks

Hint 3: Build a risk score and show it in the report

5.9 Books That Will Help

Topic Book Chapter
SELinux troubleshooting “SELinux System Administration” Troubleshooting chapter
Audit logs “The Linux Programming Interface” Audit section
Policy design “SELinux by Example” Policy chapters

5.10 Implementation Phases

Phase 1: Foundation (2-3 days)

Goals:

  • Parse AVC logs and build structured records.
  • Group records by root cause key.

Tasks:

  1. Build a parser and load fixture logs.
  2. Implement grouping and sorting.

Checkpoint: Group counts match expected fixture output.

Phase 2: Core Functionality (3-5 days)

Goals:

  • Implement remediation decision tree.
  • Add label and boolean checks.

Tasks:

  1. Integrate matchpathcon and getsebool.
  2. Generate recommendations with evidence.

Checkpoint: Recommendations match golden path fixture.

Phase 3: Polish & Edge Cases (2-3 days)

Goals:

  • Error handling and exit codes.
  • JSON output and report formatting.

Tasks:

  1. Add CLI options and structured errors.
  2. Write tests for malformed log lines.

Checkpoint: Tests pass and output is deterministic.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Parser style regex vs tokenizer tokenizer Handles order and quotes reliably
Grouping key include path or not include path Better root-cause precision
Policy suggestion auto-apply vs generate generate only Safer and reviewable

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Parsing and grouping key=value parser
Integration Tests Fixture log analysis golden path report
Edge Case Tests Missing PATH, permissive warnings and exit codes

6.2 Critical Test Cases

  1. Missing PATH record: should still produce recommendation with path=”unknown”.
  2. Permissive denial: report warning but exit code 1.
  3. Boolean already enabled: recommendation should note no action needed.

6.3 Test Data

fixtures/audit.log
fixtures/booleans.txt

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
Parsing by fixed field order Missing values Tokenize key=value pairs
Ignoring permissive denials False alarms Mark as warnings
Using audit2allow blindly Overbroad policy Require evidence and review

7.2 Debugging Strategies

  • Compare parsed output to raw ausearch lines.
  • Use small fixture logs to isolate parsing issues.

7.3 Performance Traps

  • Re-running matchpathcon for duplicate paths; cache results.

8. Extensions & Challenges

8.1 Beginner Extensions

  • Add CSV export.
  • Highlight top 5 denial sources.

8.2 Intermediate Extensions

  • Integrate with sealert for explanations.
  • Add policy query to check if allow rule exists.

8.3 Advanced Extensions

  • Build a TUI with interactive filtering.
  • Add auto-opened policy review diff.

9. Real-World Connections

9.1 Industry Applications

  • SRE tooling: automate remediation suggestions.
  • Security operations: triage denials during incidents.
  • setroubleshoot: automated SELinux diagnostics.
  • audit2allow: policy suggestion tool (use cautiously).

9.3 Interview Relevance

  • SELinux troubleshooting and policy reasoning
  • Log parsing and evidence-based remediation

10. Resources

10.1 Essential Reading

  • “SELinux System Administration” by Sven Vermeulen (troubleshooting)
  • “SELinux by Example” (policy reasoning)

10.2 Video Resources

  • SELinux troubleshooting walkthroughs (conference sessions)

10.3 Tools & Documentation

  • ausearch, aureport, audit2why, audit2allow

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain the fields in an AVC message.
  • I can justify why a labeling fix is safer than a policy rule.
  • I can explain when booleans are appropriate.

11.2 Implementation

  • All functional requirements are met.
  • Report output matches fixtures.
  • Exit codes are correct and documented.

11.3 Growth

  • I can explain the recommendation engine logic.
  • I documented why each fix was chosen.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Parses AVC logs into structured records.
  • Groups denials and prints a report.

Full Completion:

  • Adds labeling and boolean detection.
  • Generates policy skeletons with risk scores.

Excellence (Going Above & Beyond):

  • Integrates with sesearch for rule lookup.
  • Adds TUI and interactive filtering.

13 Additional Content Rules (Hard Requirements)

13.1 Determinism

  • Use fixture logs with frozen timestamps.
  • Sort output by canonical keys.

13.2 Outcome Completeness

  • Provide success and failure demos with exit codes.

13.3 Cross-Linking

  • Concepts link to §3.2, §3.7, §5.10 and related projects.

13.4 No Placeholder Text

  • All content is specific and actionable.