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
mysvcd_t
)tcp_socket
, file
)connect
, getopt
).pp
(Policy Package) file, sourced from one or more files like .te
(Type Enforcement), .if
, .fc
, etc.)/opt/mysvc/bin/mysvcd
mysvcd_t
getopt
operation on class tcp_socket
during outbound connection attempts to x.x.x.x:443
.👉 For SELinux-specific terminology, see the centralized Glossary in the README.md for this folder.
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:
denied { ... }
and tclass=...
to help identify the root cause and solution.-c
/--comm
: Command name (executable filename), not the policy name.-su
: scontext (SELinux subject context), commonly used to match the domain/type.-m
: Specifies the message type (e.g., AVC
, USER_AVC
, etc.). While -m AVC
is the most common for denials, others like USER_AVC
, SELINUX_ERR
, and USER_SELINUX_ERR
can surface in special cases (user-space denials or SELinux errors).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 ...
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 ...
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, theself
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
andtcontext
are set tomysvcd_t
in audit logs.
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 viasystemd
/SysVinit
) is not working as expected, check that you have declared allrole
andtype
permissions for the transition.
Both therole
andtype
must be authorized for transitions to succeed. Missing or misconfigured role declarations are a common source of unexpected transition failures.
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.
Check again with sesearch
:
sesearch --allow -s mysvcd_t -t mysvcd_t -c tcp_socket
Confirm the operation getopt
is now present.
netstat
to confirm connection attempts.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
sesearch
after making changes..te
file is correct, always rebuild and reinstall the module to ensure changes take effect.ausearch(8)
: Audit log search toolsesearch(1)
: SELinux policy rule search toolsemodule(8)
: SELinux policy module management