Straypenguins-Tips-Inventory

SELinux Policy Troubleshooting: Resolving Audit Denials for a Custom Service

Overview

This document demonstrates the investigation, diagnosis, and resolution steps for SELinux policy denials encountered by a custom service/domain (e.g., mysvcd_t). It describes how to identify, analyze, and resolve permission problems—using a workflow and troubleshooting checklist that can be adapted for various SELinux modules by substituting the relevant domain/type and permissions.

Related Documents


Glossary


Environment & Example Situation

👉 For SELinux-specific terminology, see the centralized Glossary in the README.md for this folder.


Procedure Outline


Diagnostic Steps

1. Identify Denied Operations

Check audit logs for SELinux denials using ausearch:

ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -su mysvcd_t

Use ausearch to efficiently locate relevant information. Here are some useful patterns:

Goal Command Example Description
All SELinux denials ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR Match message types (case-sensitive)
By process name ausearch -c mysvcd Full executable name only (exact match, not partial)
By subject domain/type ausearch -su mysvcd_t scontext (SELinux subject context), commonly used to match the domain/type
By message type ausearch -m AVC AVC: most common denials
By start time (since) ausearch -ts today
... -ts mm/dd/yy 'HH:MM:SS'
... -ts recent (means 10 min ago)
Filter by time
Fuzzy match (with grep) ausearch ... \| grep mysvcd Any line with substring
Command prefix match (with grep) ausearch ... \| grep 'comm="mysvcd' Commands starting with name

📝 Note:

Typical denial entry:

type=AVC msg=audit(...): avc: denied { getopt } for pid=... scontext=system_u:system_r:mysvcd_t:s0 ... comm="mysvcd" ... tclass=tcp_socket ...

2. Verify Running Context

Ensure the service is running in the intended SELinux domain (if it is running at all):

ps -axZ | grep [m]ysvcd

Expected output:

system_u:system_r:mysvcd_t:s0 ...

3. Check Policy Permissions

List all active permissions for the domain:

sesearch --allow -s mysvcd_t

This command lists the permissions currently active for the domain, as loaded in the system policy.
If a rule is missing from the output, something is preventing it from being active—usually a problem in the module source definition or a failed module load.

Check for a specific problematic permission:

sesearch --allow -s mysvcd_t -t mysvcd_t -c tcp_socket

-s (--source): source type/attribute name.
-t (--target): target type/attribute name.
-c (--class): object class.

Expected (correct) output:

allow mysvcd_t mysvcd_t:tcp_socket { connect create getopt };

If missing getopt:

allow mysvcd_t mysvcd_t:tcp_socket { connect create };

📝 About self in policy rules:
In SELinux policy, the self keyword refers to the case where both the source and the target are the same domain/type. For example,

allow mysvcd_t self:tcp_socket { create connect getopt };

is shorthand for

allow mysvcd_t mysvcd_t:tcp_socket { create connect getopt };

This matches rules where both scontext and tcontext are set to mysvcd_t in audit logs.


Resolution Steps

1. Update Policy Source

Check your source .te file to ensure the permission rule exists and includes all required operations (permissions), for example:

allow mysvcd_t self:tcp_socket { create connect };

Correct to:

allow mysvcd_t self:tcp_socket { create connect getopt };

Also ensure the preceding require {} clause declares all necessary type, class, attribute, etc. for the rules.
For example, your .te file should look like:

require {
    type mysvcd_t;
    class tcp_socket { create connect getopt };
}
allow mysvcd_t self:tcp_socket { create connect getopt };

Omitting something required here can cause policy compilation or installation to fail, or the rule to be ignored.
Missing references are usually highlighted in AVC denial messages.

đź’ˇ Tip:
If domain transition (switching from one SELinux domain/type to another, mainly when activating an executable via systemd/SysVinit) is not working as expected, check that you have declared all role and type permissions for the transition.
Both the role and type must be authorized for transitions to succeed. Missing or misconfigured role declarations are a common source of unexpected transition failures.

2. Rebuild and Reload Policy

checkmodule -M -m -o mysvcd.mod mysvcd.te
semodule_package -o mysvcd.pp -m mysvcd.mod
semodule -v -X 300 -i mysvcd.pp

đź’ˇ Tip: Overwriting vs. Removing Policy Modules
You can overwrite your installed SELinux policy module by simply reinstalling it (semodule -i). There is no need to remove the module first.
In fact, removing a module without first resetting labels on associated directories or files can sometimes cause issues—such as modules becoming unremovable or leaving behind remnants. Recommendation: Always update by overwriting, unless you are intentionally removing all traces of a module.

Checking Loaded Modules:
After installing, confirm the module is loaded and its types are present:

semodule -lfull | grep mysvcd && seinfo -xt | grep mysvcd

This will list the loaded SELinux module(s) and show the defined types.

đź’ˇ Tip:
If you perform these steps often, consider scripting them for convenience.
Example shell script (build-mysvcd.sh):

#!/bin/sh
show_run () {
    echo $@ ; $@
}

show_run checkmodule -M -m -o mysvcd.mod mysvcd.te
show_run semodule_package -o mysvcd.pp -m mysvcd.mod

echo "## Run below to install and check the SE-module:"
cat <<EOM
semodule -v -X 300 -i mysvcd.pp
semodule -lfull | grep mysvcd && seinfo -xt | grep mysvcd
EOM

This automates routine builds and reminds you how to verify installation.

📝 Note:
When you remove or overwrite a module, also consider whether filesystem labels need to be reset (restorecon or semanage fcontext), especially if you have changed types or paths.
For details on when and how to reset labels during module uninstallation, see:
Uninstall the policy module in Create SELinux Policy Module for Your Own Service.

3. Verify Policy is Active

Check again with sesearch:

sesearch --allow -s mysvcd_t -t mysvcd_t -c tcp_socket

Confirm the operation getopt is now present.

4. Test Service Behavior

5. If Not Solved or Another Denial is Observed

Repeat the diagnostic process starting from Step 1.

đź’ˇ Tip: Troubleshooting Sequential Permission Errors
If you encounter a series of SELinux denials—where resolving one permission leads to another denial—consider temporarily switching the system to Permissive mode:

setenforce 0
getenforce

In Permissive mode, SELinux logs denials but does not block operations. This lets you run the service and collect a complete list of required permissions from the audit logs. Be sure to return to Enforcing mode after you have corrected the policy:

setenforce 1

Key Lessons


References