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.


Reply via email to