zondag 12 juli 2009

Policy development: optional policy

If you have looked into source policy you might have noticed optional policy blocks of policy in the type enforcement source policy files. Optional policy is used to make policy modular.

If you call a interface in your policy module that is hosted by another policy module then your module is dependent on that other module. If you decide to de-install the policy module that hosts the interface that you called in your policy module than your policy will no longer be able to build. This is because you're calling shared policy that no longer exists.

To avoid these dependencies, optional policy block are used.

Let's look at some examples:


On line 244 to line 246 there is an optional policy block defined with policy that is borrowed from the gnome policy module.
This can determined since the interface is prefixed by the name (gnome) of the policy module that hosts the interface that is called by mozilla.

The interface facilitates permissions that allows firefox to connect to a unix stream socket that is owned by gnome gconf.

The interface is defined here:

(line 38 to line 55)

Let's use the semodule command to list both mozilla and gnome modules:

# semodule -l | grep gnome

gnome 2.0.0
gnomeclock 1.0.0

# semodule -l | grep mozilla
mozilla 2.0.1

We should be able to de-install both modules without getting into dependency troubles. If i decide to de-install the gnome module then the gnome_stream_connect_gconf interface becomes unavailable since it is defined in the gnome policy module that i just de-installed.

If we would have called gnome_stream_connect_gconf(mozilla_t) without using the optional policy block than we would run into trouble if we tried to de-install the gnome module. The compiler would complain about missing dependencies.

You should note that not all policy comes as a stand alone module. Some policies are not optional and they go into a single policy module called base.
As a rule keep in mind that if you can list a module with the semodule command then it can be de-installed.

If you borrow shared policy from another (optional) policy module then remember to place it into the optional policy block. For example all policy borrowed from gnome module can be placed into a optional policy block for gnome policy.

(line 225 to line 227)

These are two interfaces that are hosted by the apache policy module. Both interfaces can go into a single optional policy block since both interfaces are dependent on the same apache module.

FAQ: SELinux denies access but AVC denials can not be found.

It happens. There are a few reasons for this:

1. Silenced AVC denials (access vector cache).

In policy one can define to silently deny access vectors. This means access is denied and attempts are not logged. Such a rule (access vector) would look like this for example (fictional):

dontaudit user_t var_t:dir { read open };

When a user that operates in the user_t user domain tries to read a var_t directory object type, access is denied. The attempt that was denied would not be logged.

In general the use of "dontaudit" rules should be kept to a minimum. The issue of being denied access and not finding an audit trail for this reason should not happen often at all.

There are exceptions, like restricted user domains. These processes are restricted/limited for reason and those restrictions/limits might give violation attempts when a user operating in such a domain tries to do something that is not allowed. In this case the AVC denials are anticipated and silenced to avoid flooding of the logs with meaning less entries.

There is a way to expose these silenced AVC denials, but be aware that this may fill up your logs quicker than expected.

The semodule command used with the -DB options unloads "dontaudit" rules on-the-fly. All attempts to violate policy are now logged.

The semodule command used with the -B option builds the policy with the "dontaudit" rules included. Silenced AVC denials are back in policy.

2. User space object managers.

User space object managers are SELinux extensions on application layers. Applications that implement a SELinux Access Control Extension provides classes and permissions to be used for SELinux Policy. The application itself enforces policy that is defined using the classes and permissions it has provided.

There are only few applications that are also user space object managers. DBus implements this and this feature is enabled by default. If some access is denied and you've unloaded the "dontaudit" rules using the semodule command with -DB option, but you still cannot find any audit trail, then chances are the DBUS access control extension is responsible.

In some cases, which might be due to a bug, DBUS sends its user_avc denials to /var/log/messages instead of the expected /var/log/audit/audit.log

So it is recommended to also see /var/log/messages or dmesg if you suspect SELinux denied access but you cannot find any audit trail.

SELinux denials are called AVC denials and can also be listed using the ausearch command with -m option and avc parameter.

User space object manager denials are called USER_AVC denials and can also be listed using the ausearch command with the -m option and user_avc parameter. Note that this only works for denials logged to /var/log/audit/audit.log


If you suspect SELinux denied some access but you can not find the audit trail then consider building the policy without the "dontaudit" rules using semodule -DB. If you still cannot find any audit trail than maybe a user space object manager denied access. Look for USER_AVC denials in audit.log or look in /var/log/messages, or dmesg. The log file for the application itself may also have them.

I think the goal is to have everything log to audit.log for simplicity but at the moment this is not the case.


You can use the sesearch command to list "dontaudit" rules that are currently built-in policy. For example to list "dontaudit" rules where the httpd_t is the source domain:

sesearch --dontaudit -s httpd_t

Have a look at "man sesearch"