Your team deployed a custom daemon called vaultsyncd that synchronizes encrypted secrets between hosts. It listens on port 8470 and reads configuration files from /opt/vaultsync/data/. In permissive mode it runs fine. In enforcing mode it dies immediately with a wall of AVC denials. Your mission: write a proper SELinux policy module from scratch so this daemon runs confined under its own type.
The targeted policy ships with types for well-known daemons - httpd_t, sshd_t, named_t, and dozens more. But your custom daemon has no predefined type. Without one, it inherits the type of whatever process started it. If systemd launches it, the daemon runs as init_t or unconfined_t, which either gives it too much access or causes unpredictable denials. A custom policy module solves this by defining a dedicated type with exactly the permissions your daemon needs - nothing more.
The fastest way to generate a starting point is sepolicy generate:
This creates three critical files. The .te file (type enforcement) defines the new type and its allowed access rules. The .fc file (file contexts) maps filesystem paths to SELinux labels. The .if file (interface) defines macros that other policy modules can use to interact with your type. For most custom daemons, you will spend 90% of your time in the .te and .fc files.
A minimal type enforcement file for vaultsyncd looks like this:
Each allow rule follows the same pattern: source type, target type, object class, and a set of permissions in braces. The init_daemon_domain macro handles the transition from init_t to vaultsyncd_t when systemd starts the binary.
The file contexts file tells restorecon how to label your daemon's files:
You will see countless tutorials that tell you to pipe AVC denials into audit2allow and load the result. This works, but it is dangerous. The tool generates the most permissive rules possible to satisfy the logged denials. If your daemon tried to read /etc/shadow by accident, audit2allow will happily create a rule allowing it. Always review the output. Use audit2allow -R to get reference policy macros instead of raw allow rules when possible, and treat the output as a starting point - not a finished policy.
Once your .te and .fc files are ready, compile and install the module:
After loading, apply the new file contexts and register the port:
The vaultsyncd daemon needs to:
/opt/vaultsync/data//var/log/vaultsyncd.logYour tasks:
sepolicy generatevaultsyncd_log_t type and the appropriate allow rules for loggingcorenet_tcp_connect_http_port for outbound HTTPS connectionsausearchBonus objective: Run audit2allow against any remaining denials and explain why each suggested rule is or is not safe to add.
semanage port or define it in your .te file. Otherwise the bind will be denied.You can write, compile, and load custom SELinux policy modules for any daemon. +200 XP