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/mysvcdmysvcd_tgetopt 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).See audit(8) man page for advanced usage.
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 ...
📝 Note:
dontauditrules can hide SELinux denialsIf you see that a service behaves differently in Enforcing vs Permissive mode but
ausearch(oraudit.log) shows no AVCdeniedrecords, considerdontauditrules. A number of default SELinux policies usedontauditto suppress noisy, commonly harmless denies — this can hide valuable diagnostic information during policy troubleshooting.What to know
- Disabling
dontauditdoes not change enforcement semantics (it does not convert denies to allows). It only causes the previously suppressed denials to be written to the audit log so you can inspect them.- Because many suppressed messages may appear once
dontauditis disabled, expect a large increase in audit log volume. Re-enabledontauditwhen done.How to check whether
dontauditrules exist
- Show the number of
dontauditrules (requiressetools-consolepackage [RHEL]):seinfo --dontauditA non-zero count indicates the policy contains
dontauditrules.How to temporarily disable
dontauditto capture hidden denials
- Short option (RHEL docs / common shorthand):
semodule -DB- Long option (equivalent):
semodule --disable_dontaudit --buildAfter running either command, reproduce the problem and inspect AVC logs.
How to re-enable
dontaudit(restore normal, quieter logging)
- Short option:
semodule -B- Long option (equivalent):
semodule --enable_dontaudit --build📌 Notes and best practices:
- Perform this procedure in a controlled window (not long-term) to avoid enormous audit logs.
- After you fix the policy and reload your module, re-enable
dontaudit.
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
selfin policy rules:
In SELinux policy, theselfkeyword 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
scontextandtcontextare set tomysvcd_tin 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 allroleandtypepermissions for the transition.
Both theroleandtypemust 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 EOMThis 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 getenforceIn 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