I am trying to write a SELinux policy which after its installation will prohibit for a unconfined (or another, which can be chosen) user any subsequent SELinux policy installation. It seems that there are few ways to do this:

  1. prohibit the use of semodule so the user won't be able to install any policy. semodule has "semanage_exec_t" SELinux type. I am using object domain transition here.
  2. with the use of SELinux security class.

As for the 1st conclusion i am trying to use "domain_auto_trans" macro but this macro doesn't work for policyversion below 25. I have 24. Although i was able to check it on policyversion 28 and it worked as needed. by the way it looks like this

    policy_module(semanage_access_deny_label_B, 1.0.0)
    require {
       type unconfined_t, semanage_exec_t, semanage_t;
       role object_r;
    domain_auto_trans (unconfined_t, {semanage_exec_t semanage_t}, user_t);

TE file for the 2nd conclusion looks like this

policy_module(semanage_access_deny, 1.0.0)
require {
   type unconfined_t;
   role object_r;
   class security { compute_av compute_user compute_relabel 
   compute_create setenforce check_context load_policy setbool };
allow unconfined_t self: security compute_user;
neverallow unconfined_t self: security { compute_av setenforce check_context load_policy setbool };

The 1st way works only on the current SELinux version and the 2nd one although being successfully compiled and applied doesn't do what i planned it to do (actually it doesn't do anything at all). So the question is how to write a policy which after its installation will prohibit any subsequent SELinux policy installation for any chosen users and will work on current and previous SELinux versions?

migrated from security.stackexchange.com Jun 26 '18 at 8:52

This question came from our site for information security professionals.


Your first module has a problem: root user in unconfined_t still has the permissions and rules in place allowing selinux policy modifications. Your custom policy only applies new automatic transitions for semanage_exec_t to user_t. Process in user_t domain can't modify the policy, hence semodule, semanage, etc. fail. However, any program in unconfied domain could still modify the policy. Also, root could just relabel those semanage_exec_t labeled binaries to any unconfined type to run them.

Your second policy module doesn't do anything, because neverallow rules are compiler-checked and do not result in any rules in compiled policy. You can not use neverallow to remove/blacklist rules already included in loaded policy (and there isn't a deny statement in SELinux policy language which you could use in such fashion).

Policy compilation should issue error and fail if there are conflicting allow and neverallow rules. According to documentation, neverallow rules can be used in policy modules, but for the checks to be effective expand-check must be set to 1 in semanage.conf (possibly the reason why your module compiled successfully).

Some ways to approach your problem for preventing modifications to loaded SELinux policy:

  • Use secure_mode_policyload boolean:

    Boolean to determine whether the system permits loading policy, setting enforcing mode, and changing boolean values.

    Similarly secure_mode_insmod boolean will prevent loading additional kernel modules. These booleans can not be turned off on running system, once turned on (reboot required to turn off).

  • Configure users to more confined domains (such as user_t), which doesn't allow modifying loaded policy. Switching to root with su/sudo will not elevate to more privledged SELinux user and keeps the same SELinux enforced restrictions in place.

  • Create your own SELinux user. You could base it on a SELinux user provided by your distribution (download your distribution's policy sources). You probably should consider using some confined user as template instead of unconfined user and only add permissions you need to allow to avoid granting overly broad permissions.

    Also, if you only need to grant some limited access (transitions/rules), you could write a policy module granting the necessary access to the limited user.


When it comes down to "installing" new policy it boils down to restricting access to who can "write" and "relabelto" /etc/selinux/TYPE/policy/policy.* files.

Determine the type of that target. Use the SELinux policy analysis suite to determine what can "write" and "relabelto" that type of file. Then make sure that whatever process you do not want to be able to install policy does not have that access (directly or indirectly) to that type of file.

In addition, you probably also want to make sure that any processes that you do not want to be able to install policy do not have access to "security setenforce", and do not have physical access. Because otherwise these processes could just go around SELinux.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.