Extra security systems for Unix should be explicit, not implicit

April 23, 2007

I'm no fan of SELinux, but in stumbling over it a few times I've come to some theories about why I don't think it works. One of them, perhaps the most important one, is this:

Extra Unix security stuff needs to be simple and explicit.

Extra Unix security stuff needs to be explicit because the effective alternative is invisibility, since Unix already has one security system and most people aren't going to do very well remembering a second invisible one.

(A great deal of SELinux is implicit, in file contexts and so on, so when something goes wrong it is a mysterious failure with an invisible cause. The very existence of setroubleshoot, whose purpose is to try to make SELinux less invisible, shows the problem acutely.)

One simple change that would make SELinux a lot less invisible would be to give it its own errno value, with an accompanying useful error string. Then programs that fail because of some SELinux ailment might at least print something that points people to the cause, instead of a 'permission failed' message that just leaves the poor sysadmin frustrated because as far as they can see, the permissions are fine.

(Similar logic applies to remote filesystems; if the client thinks that everything should be OK but the server disagrees, I think you probably want to return a different errno value to the program. I'm aware that no one agrees with me here.)

A corollary to this is that I think process confinement should be an extra mechanism and be explicit; one mechanism would be that you just run a program like su to start programs in the confined setting of your choice. Then you could at least see this in places like startup scripts, and you could try it out by hand, and so on.

(I don't have a good answer for how confined processes should show up in ps output. Perhaps every confinement mode should have a UID and login assigned to it, although then you'd want the kernel to either automatically confine processes running as that UID or refuse to allow you to become that UID outside of the confinement system, so you can never have a process running as that UID that is not confined.)

Comments on this page:

By Dan.Astoorian at 2007-04-24 11:31:15:

One simple change that would make SELinux a lot less invisible would be to give it its own errno value[...]

errno is far too well established a programming interface to introduce arbitrary and incompatible changes; programmers rely on the possible errno values that POSIX says a system call may return. Introducing a new value meaning "permission denied but for a different reason than the normal permission denied" would cause more problems than it solves. It's also a slippery slope: one could argue that there should be a separate errno for "permission denied due to file ACL / extended attributes" as well.

The application should not need to know any more than "permission denied"; figuring out what denied the permission is not its job. What is needed is better debugging facilities outside the application; an example of that concept implemented incredibly well (from what I've heard) is Solaris's DTrace mechanism.

You use the term "implicit" to mean "invisible," which I don't think is really accurate: there are two distinct problems. SELinux is, in one sense, not implicit at all: it must be enabled and provided with a policy to enforce. Unfortunately, many vendors seem to have decided that it's a good idea to ship their distributions with SELinux turned on by default with a particular policy that they think is useful, so in the context of the distribution, that distinction is irrelevant: SELinux may be considered, for all intents and purposes, implicit to the distribution. That is one of the factors that makes SELinux get in the way more than it should: it's too easy for it to wind up enabled without the sysadmins, programmers and other troubleshooters of the system being aware of the policy it's enforcing.

Notwithstanding the degree of explicitness, though, even if the users know it's there, SELinux is also sufficiently invisible that people forget it's there; consequently, they often end up getting blown to bits by their own landmines, so to speak.


By cks at 2007-04-24 14:06:57:

Only in theory is errno non-expandable. In practice, no even vaguely portable and reliable program can count on getting back only specific known errno values, so you can add new errno values relatively freely.

(Perhaps this is a regrettable situation, but it's also life now, so Unix might as well take advantage of it.)

By Dan.Astoorian at 2007-04-24 16:12:26:

I never said you couldn't extend errno; what you can't do is change what an established value already means. EACCES means that permission to access an object is not allowed, and the standards all say that that's the value a conforming implementation must return when that condition occurs. That's so that an application can do something sensible if the OS tells it it doesn't have permission to access an object (such as to move on to operate on an alternative object), irrespective of the reason permission was denied.

The only way any program can be "even vaguely portable and reliable" is if it's been written to an accepted standard; that's why such standards as POSIX and X/OPEN exist, and why implementations need to stick to them even when the implementors think they're wrong.

What you seem to be advocating is adding a kludge to make the application distinguish a condition it wasn't designed to deal with by making an EACCES error look like something else. That may be a clever approach, but clever is frequently incompatible with predictable, and where software is concerned, predictable is much more valuable. Giving SELinux its own errno amounts to being annoyed at SELinux for being transparent and taking out that anger on the innocent application for not failing spectacularly enough.

If applications should have the ability to distinguish sub-conditions of EACCES (i.e., to be SELinux-aware), then an interface should be introduced to provide it--in a way that doesn't run afoul of existing standards or practice.


By cks at 2007-04-25 22:02:21:

I strongly believe that counting on errno to have specific values in specific circumstances is both dangerous and uncommon out of the narrow area of non-blocking network IO. I am pretty sure that you would have to look long and hard for a program that specifically checked for EACCES, for example.

(I wrote about part of this in SpecificErrnoDanger.)

In practice I believe it is non-portable, in that there are already existing environments that can and do return different errno values for the abstract 'I am not going to give you access to this thing that does actually exist' condition.

Written on 23 April 2007.
« Why Red Hat 7.3 is (still) so present on servers
RPC is surprisingly expensive »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Apr 23 22:49:34 2007
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.