On Wed, 5 Dec 2012 20:42:32 +0000 David Holland <dholland-tech%netbsd.org@localhost> wrote: > That may be, but it's still true of file descriptors. Traditionally > they're capabilities, and I really don't like the idea of rearranging > that arbitrarily and inconsistently. > > I think to do this correctly, exec and search on file handles needs to > be handled the same as read and write: you must open with the > corresponding O_ flag, and that then gives you a capability that > remains valid until closed (or revoke(2)'d). Ah yes! Modelling this in terms of capabilities is what I think has been missing from this discussion. Or rather, nobody (myself included) seems to have picked up on your previous mention. Of course, possessing a capability, and possessing the capability to grant that capability[1] are two different things. Is it really a good idea that any process that can execute a file should automatically be able to allow another process to do so? Conversely, there's not much point in being able to pass the capability to another process if it needs to already have execute permission. > Because passing capabilities around is potentially dangerous, if we're > going to add new capabilities we need to either be certain that no > restrictions are needed, or add a mechanism to restrict capability > passing. Since we clearly aren't certain (if anything, we're certain > that restrictions are needed), someone needs to come up with a > mechanism. Are you saying what I just said, or something else? I think it's a good idea to know how this thing can be abused before devising a mechanism for restriction. It's ok to say “we're not certain” but taking a guess risks restricting the wrong thing and leaving a hole wide open. I have a fond memory of rooting[2] a friend's (Linux) box using rmt, which his distribution had installed suid root. All his carefully set permissions on devices were rendered pointless by this one oversight. > There is a good bit of prior art we can take from in existing or > historical capability systems, so designing a suitable mechanism and > interface will probably take a bit of reading but shouldn't be very > hard. Just remember that the process root directory is also a form of > capability, and it shouldn't be that hard to figure out how to make > everything interact. > > This does mean we aren't going to be POSIX-compliant on O_EXEC and > O_SEARCH (are there any other O_ flags involved?) but I think it's > become clear that this is inevitable. When we're done we can decide if > O_EXEC and O_SEARCH and the corresponding other bits should disappear > or not when _POSIX_SOURCE and friends are defined to request strict > POSIX. There appears to be consensus on deviating from the spec. But it seems clear to me that non-compliant behaviour shouldn't be enabled if strict compliance is requested. Principle of least surprise: not implemented is a hard failure mode and easy to handle; not compliant can lead to an apparent success and a debugging nightmare. > We also need to decide if the process root dir and process current dir > are equivalent to file handles and are thus capabilities (meaning > search permission does not need to be checked again at use time) or > not. This could go either way and I don't currently have an opinion. My instinct is to say that consistency is key, and therefore considering all of these attributes as capabilities is the way to go. However, this could change the behaviour of some code. One can imagine a process A which has the ability to request that process B (with different credentials) make permission changes on its behalf. What if A asks to be denied search permission to its own cwd? Of course, this is a contrived example. Perhaps it's not a problem. > We're also going to need a way to encode capabilities such that they > can be passed down from syscall code into vfs and filesystem code. > When the only path requiring alternate forms of security check was > truncate, it was ok to deal with it on an ad hoc basis; but now there > are a lot of places that need to check either permissions or a > capability, and I really don't want to be doing it in anything other > than a systematic manner, especially in namei. The obvious answer is to pass around a reference rather than the cap itself. All operations on caps then are handled by functions/macros that set/extract values in the global table as required - no code ever touches them without going through the abstraction. I say global because I'm thinking of the case where caps are passed between processes. But there are other ways to solve that problem. Either way, file descriptors are reduced to being a local alias to the relevant capability. There may even be a cunning way to accelerate that lookup. Julian [1] I hate English. I'm talking about “able to do” vs “able to permit”. [2] Like many insomniacs, I get naughtier as the night goes on. -- 3072D/F3A66B3A Julian Yon (2012 General Use) <pgp.2012%jry.me@localhost>
Attachment:
signature.asc
Description: PGP signature