Learn SELinux - Domains, Types & Policy Modules
Episode 5 of 23

Learn SELinux - Domains, Types & Policy Modules

Reading and understanding the policy from the inside: the structure of Type Enforcement rules such as allow and neverallow, attributes and roles, reading the policy with sesearch and seinfo, and managing policy modules with semodule in the .pp and modern CIL formats.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 4 we learned to label the filesystem correctly. But labels are only half the story — labels only mean something if there are rules connecting them. This episode takes you to the heart of SELinux: the policy. We'll read Type Enforcement rules, understand the structure of allow and neverallow, get to know attributes and roles, and then manage policy modules with semodule.

By the end of this episode, you'll no longer see SELinux as a black box — you'll be able to ask the policy directly "what is this domain allowed to do?" and get a readable answer.

The Structure of Type Enforcement Rules

The most fundamental TE rule looks like:

Structure of an allow rule
allow <domain> <type> : <class> { <permissions> };

A real example you'll encounter in the policy:

text
allow httpd_t httpd_sys_content_t : file { read getattr open };

Meaning: processes in the httpd_t domain are allowed to perform the read, getattr, and open operations on objects of the file class labeled httpd_sys_content_t. That's the language whose results we've seen as "allowed" or "denied" in episode 3.

allow vs neverallow

The two most important types of rules:

  • allow — grants permission. Without an allow rule, access is automatically denied (default deny).
  • neverallow — an absolute prohibition that is checked at policy compile time. If another module tries to allow something that neverallow forbids, the policy compilation fails entirely — the system won't load the policy. This is the last line of defense that prevents admins (or bugs) from opening accesses that should stay closed.

neverallow is why you sometimes can't just "add an allow" with audit2allow: if that rule violates a neverallow, the policy refuses to compile. Understanding this saves you from frustration when developing your own policies.

Attributes & Roles

Besides domains and types, the policy knows two grouping concepts:

  • Attributes — "virtual" labels that group many types. For example, the file_type attribute covers all file types; an allow rule targeting an attribute automatically applies to all its member types. This keeps the policy concise — one rule for hundreds of types.
  • Role — the connection between an SELinux user and a domain. The role determines which domains a user is allowed to run. For example, system_r is the role for system processes, while the role on objects is always object_r. The rule connecting a role to a domain is called a role transition.

Reading the Policy: sesearch & seinfo

The tools for dissecting the policy come from the setools-console package (installed in episode 0):

Find all permissions of the httpd_t domain
sesearch --allow --source httpd_t
Output snippet
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open };
allow httpd_t httpd_sys_content_t : dir { ioctl read getattr lock open search };
allow httpd_t tmp_t : file { read write getattr setattr };

sesearch is the policy search engine: search by source domain (--source), target type (--target), or class (--class). Practical options you'll use often:

OptionFunction
sesearch --allow -s <domain>All permissions granted by a domain
sesearch --allow -t <type>All permissions targeting a type
sesearch --neverallowAll absolute prohibitions
seinfo -t -x httpd_tDetails of a type (member attributes, etc.)

While seinfo is the policy directory: it lists object types, attributes, roles, and users. An example of its use to view all existing types:

View all types and attributes
seinfo -t

A recommended workflow when debugging: find the offending domain from the AVC denial (episode 3), then ask sesearch what that domain is allowed to do. Often the answer to "why was it denied" is that the expected rule simply doesn't exist.

Managing Policy Modules: semodule

The SELinux policy is composed of modules — units that can be installed, disabled, and removed independently. The management tool is semodule:

Basic semodule operations
sudo semodule -l
sudo semodule -i myapp.pp
sudo semodule -d myapp
sudo semodule -r myapp
OptionFunction
-lList installed modules
-iInstall a new module (load into the active policy)
-dDisable a module
-rRemove a module

Modules come in two package formats:

  • .pp — the old binary format, the result of traditional policy compilation. Still widely circulated and supported for compatibility.
  • .cil — the CIL (Common Intermediate Language) format, the modern format introduced by the SELinux userspace and the standard in userspace 3.11. CIL is a mid-level language that's more expressive, readable, and the basis for writing new policies.
Example CIL module
(allow httpd_t httpd_sys_content_t (file (read getattr open)))

Notice: the same TE rule, rewritten in CIL syntax with parentheses. This is the modern face of policy development — and we'll go deeper into it in the later episodes about audit2allow and policy development.

Tip

Before installing a downloaded or self-built module, first inspect what's in it with sesearch. A single .pp or .cil module can contain many rules — including ones you're not aware of. Reading before installing is a security habit that distinguishes a conscious sysadmin from someone just copy-pasting.

Closing

In this episode 5, we've penetrated the heart of the SELinux policy: the structure of TE rules (allow, neverallow, attributes, and roles), reading the policy with sesearch and seinfo, and managing modules with semodule in the .pp and .cil formats.

The essentials to take with you:

  • An allow rule grants permission; without a rule, access is denied (default deny).
  • neverallow is enforced at compile time — violating it means the policy fails to load.
  • Attributes group types; roles connect users to domains.
  • sesearch for searching rules; seinfo for viewing policy structure.
  • semodule manages modules; .pp is the old format, .cil (CIL) is the modern format in userspace 3.11.

With the ability to read and manage policies, you've moved beyond just "copying commands". In the next episode 6, we'll discuss booleans & tunables — the on/off switches inside the policy that let you change protection behavior without rewriting rules, including setsebool, getsebool, and the built-in boolean list for various services. Stay motivated, because this skill is the bridge to flexible SELinux management in production!

Learn SELinux - Domains, Types & Policy Modules | Learn SELinux