Linux DAC and SELinux MAC security decision logic is basically very simple. Let's take an example. Assume a process called foo
running in SELinux security domain foo_t
requests read access to file /var/foo/secret
having type foo_secret_t
. SELinux is in the enforcing mode. The following happens in the Linux kernel:
foo
? What is the effective GID of process foo
? Who owns /var/foo/secret
? Does /var/foo/secret
have traditional Unix permissions that allow foo
to read the file? What about the leading directory rights and possible POSIX ACLs? If the DAC check denies read access, then processing stops and access is denied right away - SELinux checking is completely skipped.foo_t
has read access to foo_secret_t
. The result of that check decides whether read access is allowed or not.That is the access security logic. It is easy to understand and makes sense.
For a long time I believed that this fact implies that adding an SELinux policy to an application can never worsen security. On the contrary, adding a policy should improve security, because SELinux MAC checks are in addition to the traditional DAC rules. But does adding an SELinux policy really always improve application security? Can we find a counterexample proving that sometimes SELinux policy checks could make application security worse?
It turns out that the answer to the latter question is "yes". For the vast majority of cases, adding an SELinux policy improves security, or at any rate, it does not make it worse. But in some circumstances an SELinux policy could indeed worsen application security.
See the following C99 program fragment:
bool allow_access = true; check_access("/var/foo/access.db", &allow_access); if (allow_access == true) { transfer_dollars(amount, source_account_id, destination_account_id); return SUCCESS_TRANSFER_DOLLARS; } else { return DENIED_TRANSFER_DOLLARS; }
This fragment is flawed in two ways:
allow_access
should default to false
. Allowing access by default is bad for security. But for the sake of argument, we assume it is set to true
.check_access()
reads access authorization data from database file /var/foo/access.db
and stores the result to allow_access
via a pointer. Again, for the sake of argument, let's assume that check_access()
function returns a boolean value indicating whether performing the access check succeeded or not. In this case the programmer has ignored the return value, and that is the second flaw in our program fragment.So we have a pretty buggy application program to begin with, but it works fine when SELinux is not activated, because the standard Linux DAC rules allow access to authorization database file /var/foo/access.db
.
Next assume that file /var/foo/access.db
has SELinux file context foo_accessdb_t
. Further assume that SELinux policy has been loaded for the application, but unfortunately the policy author has forgotten to allow the application read permission to file type foo_accessdb_t
.
Due to the SELinux extra checking, read access to /var/foo/access.db
is now denied. That causes function check_access()
to fail, but because the application programmer ignored the return value, allow_access
is true
and transfer_dollars()
gets called! Now if /var/foo/access.db
authorization data had denied access, adding SELinux policy just mistakenly allowed transferring dollars from one bank account to another!
This shows that in some unfortunate circumstances SELinux policy can make application security worse. If you insist that allowing bank transfer when it should be disallowed is not a security issue per se, your point may have some merit. But it is perhaps useless to argue about semantics here, because clearly adding an SELinux policy can make matters worse, whether we choose to call it a security issue or not.
In conclusion, when both the application logic and SELinux policy contain sufficient mistakes, it is sometimes possible that adding SELinux policy worsens application security. In our example case just fixing the application logic would have prevented the malfunction. We assumed that the SELinux policy was flawed in the way that it denied access to /var/foo/access.db
. However, the application programmer should have been more careful with his or her code, and I believe that in the real world situations SELinux policy will improve security in practically all cases.
It is of course true that incorrect SELinux policies can make applications misbehave or even terminate, but I suppose that those cases rarely affect application security.
It can also be argued that SELinux policy never worsens application security in the narrower sense of allowing more access to system resources compared to DAC checks only. That point is admittedly valid.