Messages in this thread | | | Date | Thu, 15 Apr 1999 18:34:19 -0400 (EDT) | Subject | Re: caps in elf headers: use the sticky bit! | From | tytso@mit ... |
| |
Date: Wed, 14 Apr 1999 22:41:44 -0400 (EDT) From: "David L. Parsley (lkml account)" <kparse@salem.k12.va.us>
Well, I think Ted freely exercises his right to ignore us. ;-)
No, it's because I've been travelling --- some of us have real jobs and can't afford to engage a debate which is taking up a huge amount of the bandwidth on linux-kernel at the same level of intensity that you all have been using. (Which is a polite way of saying, "Wow, you all have been flaming a lot" :-)
I have been tracking the debate, and let me try to send one huge message which answers a few arguments, tries to summarize where I think every one is at in this debate, and to give some recommendations about how I think we should resolve things.
Date: Wed, 14 Apr 1999 16:03:25 +0200 From: Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
I do not see why setting inheritable set should be privileged.
In traditional unix, every utility has inheritable set set to FULL by default. I do not think it is good idea to change that.
I have to disagree; making inheritible set to be NULL by default, and only allowing someone with privileges to set the inheritable set is extremely important.
Consider that there are many security holes in Unix which are caused by the fact that by default processes inherit full privleges. For example, consider the old security problem where /usr/ucb/Mail used the "more" pager, and you could cause "more" to cause a shell to be executed by using the '!' command to more. Since /usr/ucb/Mail used to be setuid root, you could get a root shell that way! Oops. This has been fixed in modern Unix systems, but shows that you have to be extremely paranoid when you write setuid programs, less you fall into similar traps.
The problem here is that /usr/ucb/Mail was a program where the author at least knew that it was supposed to be installed setuid, and so he could take care. However, the author of the "more" program probably never considered that it was a security sensitive program, and should take special measures before deciding whether or not to allow the '!' command to work. Since "more" wasn't designed to be a high-security program, it should never inherit setuid privileges or capabilities.
The problem was solved in /usr/ucb/Mail by changing it do drop privileges before forking "more", but it only takes one programmer to forget to do that, and your goose is cooked. So in a full capabilities system, by default processes do not inherit capabilities. In effect, the drop of privileges is done automatically. This is a good thing.
Also note that because of this it means that a lot of executables will have capability sets --- including programs like cp and rm, if you want a system administrator with a privileged shell to be able to run cp and rm and have them inhert the capabilities of the privileged shell process. As a result, this completely rules out the setuid root idea, because although cp and rm might not have any "forced" capabilities, they would have some number of "inherited" capability sets, and the ***last*** thing you want is for cp and rm to be setuid root if you boot a non-capability aware kernel.
Face it, using a full capability system is a completely different security model; it's different from the traditional Unix model. But that's OK. I don't expect everyone to immediately switch to it; it will take a lot of time. In fact, I don't think it will ever see widespread use until some distribution makes it an option and works out all of the system administration issues.
Which brings us to the question of what people mean by "capabilities". There are at least three definitions of "capabilities" floating around. The first is the one which Andrej Presern asks for, which is the academic C.S. definition of "capability". This is the model where all accesses are mediated by magic tokens which are called capabilities, which can be passed around between functions and between programs/processes. In order to actually gain access to a file, you have to present a capability which gives you the right to read it. This means that the open system call would require a new argument, which would be the "capability". Your user id has no meaning, and there is no "capability set" associated with a process. This is actually a very nice model, since it means that there is no implicit set of privileges associated with your process. Instead, all accesses are mediated via explicit use of capabilities for which your process has access, and the application program has to explicitly select which capability (out of potentially dozens or hundreds) it might have when it calls each and every system call.
The only problem with this model is that it is hopeless impractical. It involves making a completely change to the entire POSIX API, and a system which used this would not be able to use any of the programs ever written for Unix or POSIX systems, since it requires a change to the fundamental OS API. So, no one besides Andrej has ever agitated for this kind of "capabilities", and this is indeed something for which you might as well rewrite Linux from scratch, and it will fail since none of the existing Unix tools could be trivially ported to it.
The second model of "capabilities" is the one which folks like Pavel have argued for, and which I will call "capabilities lite". The argument here is for something which doesn't require making any changes to tar, cp, or any filesystem specific changes. The main goal is to solve the setuid root executable problem, but taken to its logical extreme, this model only makes sense if you still have a root account and you don't support the "inherited" capabilities set. That is, by default, all processes still inherit the capabilities of their parents across exec()'s. This has some of the advantages of the "full capabilities" model (described below), but it is a pale, castrated model of the full POSIX capabilties design. The main argument for adopting this seems to be as a short-cut, and possibly because some of the proponents may not understand all of the advantages of the full capabilities model.
The final model is the one that I and others who have been involved from the linux-privs project from the beginning have been argueing for, and that's the full capabilities model as worked on by the POSIX subcommittee. This model at its fundamental core does require making changes to the filesystem, and to programs like tar.(*) It also does require making fundamental changes in how a system is configured, and administered, and how system administrators go about their daily business. I expect at least at first, people will only use capabilities in the "capabilities lite" mode. That is, they will simply only give sendmail the few limited privileges it needs, and not actually try to make root go away. But I think it's really important that we not completely rule out the full capabilities model as originally envisioned by the POSIX subcommittee. It has a lot of advantages that the "capabilities lite" model doesn't have, and it's basically as far as you can take capabilities while still being true to the fundamental Unix design. It may not be as far as Andrej would like, but it's as far as you can practically go.
So, given that, what do we do? I think we should strive for the full capabilities model as enviisioned by POSIX. Yes, it's more work, but at the end of the day, you end up with a much great set of advantages. It also allows us to be compatible with other Secure OS's that have been implemented, and with the POSIX standard if/when it ever gets revived and completed.
The main thing that had been holding up the full capabilities folks had been the necessary ext2 changes so that you could store the capabilties information in the the filesystem, attached to the file. This is what Secure Solaris and Secure HPUX does, and it's what the POSIX draft clearly assumed how this would be implemented. The problem was that doing this in a clean way is non-trivial and Stephen and I both haven't had the time to take the initial set of patches which tried to implement this and clean them up. This is our fault, and those folks who came up with the hack of storing them in the ELF headers was trying to get around the fact that we couldn't get support into the ext2 filesystem quickly enough. Fair enough.
What I would suggest is either using a combination of the sticky bit plus the immutable flag, *or* define a new ext2 flag which means "this file has capability information". The second is probably the better choice, and since it's only a bit in the flags word, it's easy enough to implement. Now, people will inevitably complain that this means you can't use other filesystems. That's correct. And I think, that's OK. As I mentioned, all of the other Secure OS's that have done this have assumed filesystem support. And you wouldn't want to use capabilities over NFS anyway, since NFS stands for No File Security. People who use capabilities are generally serious about their security, and it's easy enough to corrupt an executable going over the network via NFS to insert an attacker's trojan horse code. So running setuid programs over NFS is a *really* bad idea to begin with.
By using a special ext2 flag meaning "there be capabilities here", and using the ELF header hack, it means that you do allow a program to be setuid daemon as well as having capabilities; and it allows you to build a system with the full set of capabilities in the POSIX capabilities models. It does mean that we will need to extend some tools and build a few new ones. In addition to writing a setuid scanner, we will need to write a capability scanner. But in the long run, I think the extra effort will be worth it.
- Ted
(*) Secure HPUX has a very clever way of hiding the capabilities information in a tar file such that non-capability-aware tar programs can still read tar files with capability information. Basically, the capability information is stored in the tar file first, with a flag marking it as containing capability information, and with the same name as the file for which the capability information is for. It is then followed by the actual data contents of that executable. A non-capability aware tar program doing an extract of that tar file will ignore the flag indicating the contents of the capability information, write the capability information as a file to disk, and then when it sees the second file record, it overwrites the first file with actual data contents of the file, since it has the same name as the first.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |