Someone's pointed this thread out to me, so I'm going to shove an oar in following a few posts. I've done a fair bit of security work, so feel free to ask me to explain, justify or provide references for anything.
On Wed, 2005-04-13 at 17:01 -0400, Dan Sugalski wrote: > All security is done on a per-interpreter basis. (really on a > per-thread basis, but since we're one-thread per interpreter it's > essentially the same thing) What you actually mean (or what I believe you _should_ mean) is per-context, in the lambda-calculus sense of context. See notes below about continuations. > QUOTAs are limits on the number of resources or operations that an > interpreter an allocate or perform, either in absolute terms (i.e. > allocate no more than 10M of memory) or relative terms (i.e. can do > only 10 IO operations per second). Quotas are tracked by parrot, and > cover: The ability to manipulate and exceed QUOTAs should be controlled in dynamic context. > PRIVILEGEs are permissions to do certain things. Parrot will have a > number of privileges it checks before doing dangerous operations, and > user code may also assign and check privileges. > > Normally parrot runs with no quotas and no privilege checking. This > is the fastest way to run. Code may at any time enable privilege Actually, you can do privilege checking in an efficient engine, even using most of the reflection systems, with almost no overhead. See Java. > and/or quota checking. Once enabled code must have proper privileges > to disable it again. Typically AllPermission, otherwise you have the ability to perform privilege escalation. > Each running thread has two sets of privileges -- the active > privileges and the enableable privileges. Active privs are what's > actually in force at the moment, and can be dropped at any time. The > enableable privs are ones that code can turn on. It's possible to > have an active priv that's not in the enableable set, in which case > the current running code is allowed to do something but as soon as > the privilege is dropped it can't be re-enabled. Enableable privileges are usually called static privileges and are usually defined as the privileges held statically by the current object, or if we read ahead to your next point, subroutine. > Additionally, subroutines may be marked as having privileges, which > means that as long as control is inside the sub the priv in question > is enabled. This allows for code that has elevated privs, generally > system-level code. Please no. Privileges should be explicitly granted. You have just described the Unix SUID model, where as long as control is inside a root-owned daemon (for daemon, read subroutine), the root privilege is enabled. This always leads to privilege escalation and is BAD. What you _should_ mean, according to all prior research, is that "No code may be inside that routine and still hold a privilege not held by the routine". In shorter form, "The dynamic (current) privilege set must not exceed the static privilege set of any routine on the stack". A slightly different formulation applies for data inspection systems. See footnote. > Continuations, when taken, capture the current set of active and > enableable privs, and when invoked those privs are put into place. > (This is a spot that will require some thought, since there's a > potential for privilege leaks which worries me here) Non-continuation > invokables (subs and methods) maintain the current set of privs, plus > possibly adding the sub-specific privs. If you perform the above step correctly, then capturing a context and including it in future access control checks is not hard. Java does this by capturing a current AccessControlContext when a new ClassLoader is created in a thread to be used in a different thread. No code loaded by that ClassLoader IN ANY THREAD may exceed the privileges of the thread which created the classloader at the time it created it. > It's actually pretty straightforward, the hard part being the whole > "don't screw up when implementing" thing, along with designing the > base set of privs. Personally I think taking the VMS priv and quota > system as a base is a good way to go -- it's well-respected and > well-tested, and so far as I know theoretically sound. Unix's priv > model's a lot more primitive, and I don't think it's the one to take. > (We could invent our own, but history shows that people who invent > their own security system invent ones that suck, so that looks like > something worth avoiding) Better systems to inspect would be Java (stack inspection), Perl5 (data inspection). Please do not confuse the choice of privilege set and logic over it (authorisation system) with the mechanism for identifying the current set of privileges (identification of current principal). The key difference in security between stack inspection and data inspection systems for the purposes of parrot is that stack inspection considers for security purposes the dynamic context of the thread, but permits untrusted returned values to participate in computation, while data inspection does not permit this, but allows the evaluation of a closed (in the lambda-sense) expression in an untrusted dynamic context. S.