From Scratch: A simple systemd service with SELinux
The information on this page is largely derived, with necessary modifications, from Creating and enforcing an SELinux policy for a custom application.
Prerequisites
dnf -y install selinux-policy-devel setroubleshoot-server
dnf -y group install 'Development Tools'
# needed for at least g++ and rpmbuild. Not sure if anything else is needed from this group.
Become root
All of this documentation is to be completed as root.
Creating the service
Create mydaemon.cpp
cat > mydaemon.cpp << EOF
#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>
#include <thread>
using namespace std;
int main() {
while (1) {
time_t t = chrono::system_clock::to_time_t(chrono::system_clock::now());
ofstream MyFile("/var/log/mydaemon.log", ios_base::app); // app = append, not overwrite
MyFile << ctime(&t);
MyFile.close();
this_thread::sleep_for(chrono::milliseconds(5000));
}
}
EOF
Build it
g++ -o /usr/local/bin/mydaemon mydaemon.cpp
Create the systemd unit
By default, the unit file has selinux context that systemd cannot access, so fix that and load it:
Try to start the service. Notice it fails.
Notice that it's running in unconfined_t
Generate a custom policy for the daemon:
Build it
Note that the setup script relabels the daemon to the newly created domain mydaemon_exec_t
Temporarily set selinux to permissive and clear the audit log
Restart the daemon, and check that it now runs confined by SELinux:
For your information. (Just get a look at what selinux would have blocked.)
Build whatever new policy you need
Re-enable selinux, restart the daemon, confirm that it’s working properly