Yesterday I received an email from someone who was attempting to write SELinux policy for a daemon process, "abcd", that he was being required to run on his systems.
Here's the problem: the ****** agent runs as root and has the ability to
make changes to system configuration files. So deploying this agent
means handing over root-level control of all of my RHEL servers to
people I don't know and who have no accountability to my system owner or
authorizing official. ..... really, really
uncomfortable about this and want to protect our system from
unauthorized changes inflicted by some panicking yabbo ....
This seems like a job for SELinux. Our RHEL7 baseline has SELinux
enforcing (AWESOME) already, so I figured we just need to write a custom policy
that defines a type for the ******* agent process (abcd_t) and confines
that so that it can only access the agent's own data directories.
We did that, and it's not working out. Once we start the confined
agent, it spews such a massive volume of AVC denials that it threatens
to fill the log volume and the agent never actually starts. There are
way too many errors for the usual 'read log/allow exception' workflow to
be viable. My guess is the agent is trying to read a bunch of sensitive
system files and choking because SELinux won't let it.
Have you got any advice or ideas here?
Here is my response:
I need to see the AVC's to fully diagnose. But usually there is a type attribute for these things. Type attributes are basically names for groups of types. A common usecase for an attribute would be group all the process types on the system. In SELinux we call these domains, so we created a domain attribute. I would figure you are seeing something like abcd_t is trying to list the processes in /proc. (This is basically the equivalent of running ps -ef ) All process types on the system have the domain attribute. Instead of adding an allow rule for abcd_t to read every process type, you could just use the domain attribute.
allow abcd_t domain:dir list_dir_perms;
allow abcd_t domain:file read_file_perms;
allow abcd_t domain:lnk_file read_lnk_file_perms;
These rules allow abcd_t processes to read all of the data in /proc about processes. Better yet, there is a SELinux interface that implements this which you could use.
Another quick and dirty one would be to allow abcd_t to read all files on the system. All file types have the file_type attribute. If you wanted to allow abcd_t to read all files on your system, you could do:
A slightly more security version of this would be to allow it to read all non security files.
This would allow abcd_t to read all files except for files like /etc/shadow.
BTW, there are also big interfaces to "dontaudit" a process from reading all files on your systme. files_dontaudit_getattr_all_files(abcd_t)
How do I find out the attributes on the system?
If you want to see attributes associated with a type, you can use the seinfo command.
You can list all of the attributes on in selinux policy using the following:
If I want to look at attributes on a specific type, I can use the following seinfo command:
> seinfo -tusr_t -x
type usr_t, base_file_type, base_ro_file_type, entry_type, exec_type, file_type, mountpoint, non_auth_file_type, non_security_file_type;
Types your processes can write to.
When writing SELinux policy I always worry more about what the processes can write then what they read, although obviously there are lots of files that I don't want processes to be able to read. But the way a hacked process is going to attack my system is by writing to it.
Now when it comes to adding rules and types for what the abcd_t process can write, that should be more specific.
Look at other policy files to inspiration:
Often when I write policy, or code in general, I look at examples. The best examples of existing policy are in the source of selinux-policy package, you can get all of them from github.com
git clone email@example.com:fedora-selinux/selinux-po
Have a look around...
Using SELinux Attributes and Interfaces make grouping of a lot of rules easier for writing policy.