Introduction of deny rules for SELinux policy

After a few years, I’m glad I can share some SELinux updates. 🙂

For quite some time, I’ve encountered inquiries regarding the potential inclusion of a feature in the SELinux userspace that would facilitate the removal of SELinux rules from the system. Such functionality would indeed be beneficial, considering that SELinux policies utilized in operating systems like Fedora, CentOS, and RHEL are intricate, allowing numerous common operations. However, for specific use cases, this might not align with your preferences. Instead, you might aim to tighten the policy further.

So, what are the options? Let’s discuss several of them:

  1. Implementing a completely new SELinux policy for your OS. This approach is extremely time-consuming and complex. Given the resource constraints, it’s unlikely that there will be enough resources available to pursue this option.
  2. Replacing the affected SELinux policy module with your modifications. This solution also demands proficiency in SELinux policy writing, and it could prove challenging to remove just one rule within the policy module for replacement.
  3. Creating a new SELinux policy module with deny-type rules. With the new functionality introduced in the SELinux userspace since version 3.6, you can craft a custom module with rules incorporating the “deny” keyword to selectively drop specific rules. Let’s give it a try!

Let’s concentrate on the following use-case: You’re employing the confined user “user_u” as a tester on a Linux system. This confined user is allowed to utilize generic system tools, but you specifically want to prevent SSH connections to other systems. How can this be achieved using the new feature?

“tester” user is confined by SELinux as “user_u”:

[root@fedorabox ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *
tester               user_u               s0                   *

As you can see without any SELinux modification you’re able to use ssh as user “tester”:

[tester@fedorabox ~]$ ssh tester@localhost
[tester@fedorabox ~]$

Let’s deny it!

[root@fedorabox ~]# cat << EOF > denyrules.cil
(deny user_t ssh_exec_t (file (execute open getattr read)))
EOF
[root@fedorabox ~]# semodule -i denyrules.cil
[root@fedorabox ~]# getenforce 
Enforcing

We’ve removed the allow rule for the user_t to execute any binary file labeled as ssh_exec_t, thus preventing user_t from executing /usr/bin/ssh.

[tester@fedorabox ~]$ id -Z 
user_u:user_r:user_t:s0 
[tester@fedorabox ~]$ ssh localhost
-bash: /usr/bin/ssh: Permission denied 

This is just a simple example of how to restrict certain operations for a confined SELinux user, which are allowed in the default distribution policy, to tailor it to your specific needs. In general, I believe the “deny rules” feature will enable system administrators to customize the SELinux policy more precisely for their requirements without the need to write custom SELinux policy modules from scratch.