Re: A sketch of the security model

2005-04-16 Thread Michael Walter
On 4/15/05, Shevek [EMAIL PROTECTED] wrote:
  How can dropping a privilege for the duration of a (dynamic) scope be
  implemented? Does this need to be implemented via a parrot intrinsic,
  such as:
 
without_privs(list_of_privs, code_to_be_run_without_these_privs);
 
  ..or is it possible to do so with the primitives you sketched out above?
 
 This is usually done by creating a function f(code) { code() } without
 any static privileges in list_of_privs.

 To evaluate a function g()
 without those privileges, evaluate f(g), and the natural mechanisms of
 the interpreter will ensure that these privileges are not held during
 g().

I understand, thanks.
Michael


Re: A sketch of the security model

2005-04-15 Thread Shevek
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 

Re: A sketch of the security model

2005-04-15 Thread Shevek
On Wed, 2005-04-13 at 17:51 -0400, Aaron Sherman wrote:
 On Wed, 2005-04-13 at 17:01, Dan Sugalski wrote:
  So here's what I was thinking of for Parrot's security and quota 
  model. (Note that none of this is actually *implemented* yet...)
 [...]
  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)
 
 VMS at least *is* a priv-based security model, but VMS privs are not
 appropriate for parrot on the whole.

The best known model for privileges (logic of authorisation over) is
that of Oracle, RT, etc, where access over privileges is transitive.
Will find good references on request/when I have more time. Bad
references are available from Ravi Sandhu, but he doesn't handle
transitivity or modification of rights well, if at all.

S.




Re: A sketch of the security model

2005-04-15 Thread Shevek
On Thu, 2005-04-14 at 09:51 -0700, Dave Whipp wrote:
 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)
 ...
 * Number of open files
 * IO operations/sec
 * IO operations total
 ...
 
 Can an application get more resources simply by spawning threads? If 

Well, given that a child thread's dynamic access control context should
include the dynamic context of the parent thread at the point where the
thread was spawned, No.

What I describe is a (provably) correct implementation.

 the answer is no, parent and child must divide share their quotas then 
 there is a load balancing problem. If the answer is yes, then there's 

There is no load balancing problem assuming you are synchronized on the
thread-create point, which is not a major overhead, since that pretty
much has to be a synchronization point in the kernel anyway.

 no real protection at all. A threads-per-second limit isn't an answer 
 here, either (a malicious app could sit around for a few hours, 
 launching threads at a low intensity, until it has enough to bring down 
 the system).
 
 Is a thread really the right thing to apply these limits to? It seems to 

Limits are applied to privilege sets, not to threads.

 me that there needs to be some sort of token (cf. cash; cf capability) 
 that an application can obtain/spend/refresh to do these ops. An 

Yes, that's about the same.

 application could share its token(s) with any threads it creates. It 
 could probably even loan its token to a backgroud thread that does 
 some operation on behalf of many other threads.

Preferably not. I fear the concept of being able to hand out privileges
to low privilege threads. If the low privilege thread has access to a
(willing) object with static privileges allowing the operation, then
that object should perform the operation on behalf of the thread in a
dynamic context created by a 'grant' operation (See Fournet and Gordon,
2003). If the low privilege thread is made up entirely of low privilege
objects, then it shouldn't have the privilege under any circumstances.

S.




Re: A sketch of the security model

2005-04-15 Thread Shevek
On Wed, 2005-04-13 at 22:03 -0400, Michael Walter wrote:
 Dan,
 
 On 4/13/05, Dan Sugalski [EMAIL PROTECTED] 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)
 Just to get me back on track: Does this mean that when you spawn a
 thread, a separate interpreter runs in/manages that thread, or
 something else?
 
  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.
 
 How can dropping a privilege for the duration of a (dynamic) scope be
 implemented? Does this need to be implemented via a parrot intrinsic,
 such as:
 
   without_privs(list_of_privs, code_to_be_run_without_these_privs);
 
 ..or is it possible to do so with the primitives you sketched out above?

This is usually done by creating a function f(code) { code() } without
any static privileges in list_of_privs. To evaluate a function g()
without those privileges, evaluate f(g), and the natural mechanisms of
the interpreter will ensure that these privileges are not held during
g().

  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.
 
 Does the code marking a subroutines must have any other privilege than
 the one it is marking the subroutine with?
 
  ... Non-continuation
  invokables (subs and methods) maintain the current set of privs, plus
  possibly adding the sub-specific privs.
 
 Same for closures?

Closures may also capture a concept of the current context, which is
used when they are evaluated. This is critical in, for example, the case
of system code with higher static privileges returning a closure to a
low privilege object which may evaluate it at any time.

a) The closure must not have any privileges not held by the low
privilege object, so clearly it cannot just hold its static privilege
set, it must capture a current context.

b) If it does wish to have higher privilege (very common), it may grant
(Fournet+Gordon,2003) these privileges in a dynamic scope bounded below
by itself.

S.




Re: A sketch of the security model

2005-04-15 Thread Shevek
On Thu, 2005-04-14 at 09:11 -0400, Dan Sugalski wrote:
 At 10:03 PM -0400 4/13/05, Michael Walter wrote:

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.
 
 How can dropping a privilege for the duration of a (dynamic) scope be
 implemented? Does this need to be implemented via a parrot intrinsic,
 such as:
 
without_privs(list_of_privs, code_to_be_run_without_these_privs);
 
 ..or is it possible to do so with the primitives you sketched out above?
 
 When a priv is dropped it stays dropped until it's reinstated. If 
 code drops a priv that it can't re-enable then the priv is gone. 
 (There are going to be issues with privileges attached to 
 continuations, since this could potentially mean that dropped privs 
 get un-dropped when you invoke a return continuation, though dropping 
 a privilege could ripple up the return continuation chain)

Reinstating privileges when you return is normal, since potentially
malicious code and data has now been removed from the stack.

If you do NOT do it this way, then every piece of code must know the
privileges of every child piece of code it calls (bye-bye virtual base
classes with user implementations).

See http://research.microsoft.com/~adg/Publications/MSR-TR-2001-103.pdf

The ability to explicitly reenable a privilege via an opcode, rather
than via the removal of the malicious party from the computation (by
return) is almost definitely a bad idea. If you protect this opcode
using some security mechanism, you will rapidly find that security
mechanism can supersede the functionality provided by the opcode.

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.
 
 Does the code marking a subroutines must have any other privilege than
 the one it is marking the subroutine with?
 
 Dunno, that's something we'll need to work out. It's possible that 
 sub marking needs to be done externally -- that is, it's bytecode 
 metadata or something like that which requires system privileges of 
 some sort to set. (Though there are issues with that) Marking code as 
 privileged is really a system administration task, though we've not 
 really put much thought into administering a parrot system yet.

Actually, what usually happens is that subroutines (etc) are associated
with a responsible party (principal), and privileges are granted to the
principal; thus finding out the privileges of an opcode requires an
extra indirection. This is not a problem.

... Non-continuation
   invokables (subs and methods) maintain the current set of privs, plus
   possibly adding the sub-specific privs.
 Same for closures?
 
 Yeah, I think so.

No, as before. You cannot execute based only on static privileges - this
is what Unix does, and the Unix model is broken. You need either a stack
inspection or a data inspection model, or a combination of the two. Ask
me if you want formal descriptions or implementation details of these
models.

S.




Re: A sketch of the security model

2005-04-14 Thread Dan Sugalski
At 10:03 PM -0400 4/13/05, Michael Walter wrote:
Dan,
On 4/13/05, Dan Sugalski [EMAIL PROTECTED] 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)
Just to get me back on track: Does this mean that when you spawn a
thread, a separate interpreter runs in/manages that thread, or
something else?
We'd decided that each thread has its own interpreter. Parrot doesn't 
get any lighter-weight than an interpreter, since trying to have 
multiple threads of control share an interpreter seems to be a good 
way to die a horrible death.

  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.
How can dropping a privilege for the duration of a (dynamic) scope be
implemented? Does this need to be implemented via a parrot intrinsic,
such as:
  without_privs(list_of_privs, code_to_be_run_without_these_privs);
..or is it possible to do so with the primitives you sketched out above?
When a priv is dropped it stays dropped until it's reinstated. If 
code drops a priv that it can't re-enable then the priv is gone. 
(There are going to be issues with privileges attached to 
continuations, since this could potentially mean that dropped privs 
get un-dropped when you invoke a return continuation, though dropping 
a privilege could ripple up the return continuation chain)

  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.
Does the code marking a subroutines must have any other privilege than
the one it is marking the subroutine with?
Dunno, that's something we'll need to work out. It's possible that 
sub marking needs to be done externally -- that is, it's bytecode 
metadata or something like that which requires system privileges of 
some sort to set. (Though there are issues with that) Marking code as 
privileged is really a system administration task, though we've not 
really put much thought into administering a parrot system yet.

  ... Non-continuation
 invokables (subs and methods) maintain the current set of privs, plus
 possibly adding the sub-specific privs.
Same for closures?
Yeah, I think so.
--
Dan
--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A sketch of the security model

2005-04-14 Thread Aaron Sherman
On Thu, 2005-04-14 at 09:11, Dan Sugalski wrote:
 At 10:03 PM -0400 4/13/05, Michael Walter wrote:

 On 4/13/05, Dan Sugalski [EMAIL PROTECTED] 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)

 Just to get me back on track: Does this mean that when you spawn a
 thread, a separate interpreter runs in/manages that thread, or
 something else?
 
 We'd decided that each thread has its own interpreter. Parrot doesn't 
 get any lighter-weight than an interpreter, since trying to have 
 multiple threads of control share an interpreter seems to be a good 
 way to die a horrible death.

So to follow up on Michael's question: does this mean that you spawn a
new thread, instance an interpreter, and then begin executing shared
code? What about data? I assume that all has to be shared, since shared
data is a fundamental piece of any threaded application's assumptions.

-- 
Aaron Sherman [EMAIL PROTECTED]
Senior Systems Engineer and Toolsmith
It's the sound of a satellite saying, 'get me down!' -Shriekback




Re: A sketch of the security model

2005-04-14 Thread Dan Sugalski
At 10:44 AM -0400 4/14/05, Aaron Sherman wrote:
On Thu, 2005-04-14 at 09:11, Dan Sugalski wrote:
 At 10:03 PM -0400 4/13/05, Michael Walter wrote:

 On 4/13/05, Dan Sugalski [EMAIL PROTECTED] 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)

 Just to get me back on track: Does this mean that when you spawn a
 thread, a separate interpreter runs in/manages that thread, or
 something else?
 We'd decided that each thread has its own interpreter. Parrot doesn't
 get any lighter-weight than an interpreter, since trying to have
 multiple threads of control share an interpreter seems to be a good
 way to die a horrible death.
So to follow up on Michael's question: does this mean that you spawn a
new thread, instance an interpreter, and then begin executing shared
code?
Yes.
 What about data?
Data needs to be explicitly shared.
--
Dan
--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A sketch of the security model

2005-04-14 Thread Dave Whipp
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)
...
   * Number of open files
   * IO operations/sec
   * IO operations total
...
Can an application get more resources simply by spawning threads? If 
the answer is no, parent and child must divide share their quotas then 
there is a load balancing problem. If the answer is yes, then there's 
no real protection at all. A threads-per-second limit isn't an answer 
here, either (a malicious app could sit around for a few hours, 
launching threads at a low intensity, until it has enough to bring down 
the system).

Is a thread really the right thing to apply these limits to? It seems to 
me that there needs to be some sort of token (cf. cash; cf capability) 
that an application can obtain/spend/refresh to do these ops. An 
application could share its token(s) with any threads it creates. It 
could probably even loan its token to a backgroud thread that does 
some operation on behalf of many other threads.


Re: A sketch of the security model

2005-04-14 Thread Dan Sugalski
At 5:51 PM -0400 4/13/05, Aaron Sherman wrote:
On Wed, 2005-04-13 at 17:01, Dan Sugalski wrote:
 So here's what I was thinking of for Parrot's security and quota
 model. (Note that none of this is actually *implemented* yet...)
[...]
 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)
VMS at least *is* a priv-based security model, but VMS privs are not
appropriate for parrot on the whole.
Right. The privileges themselves are generally inappropriate for our 
use, which is fine. It's the model that I'm interested in, as it's 
the model that gets screwed up so badly, or so I'm told.

Anyway, a number of people I deeply respect (and who do this sort of 
thing for a living, at deep levels) have told me flat-out that we're 
better not having a security system than we are trying to roll our 
own, and the common response to We're lifting VMS' has been Good. 
Do that.

I think it would be easier to start from scratch, personally. I
understand your concerns, but I don't think you run any less risk by
creating a new VM security model out of an OS security model than you do
by creating a new one. They both create many opportunities to make a
mistake.
That's not been the general consensus I've seen from people doing 
security research and implementation. This is an area that I've no 
real experience doing any sort of design in, and the people who have 
the experience say not to, so I think it best to take them at their 
word.

If you really want to reduce the chances that you'll make a mistake,
swipe the security model from JVM or CLR and start with that. At least
those have been tested in the large, and map closer to what Parrot wants
to do than VMS.
The problem is twofold with those. First, there's some indications 
that they're busted, and second (and more importantly) they're both 
very coarse-grained, and that leads to excessive privs being handed 
out, which increases your exposure to damage. If a library routine 
needs to potentially exceed memory quotas we'd rather not give it the 
equivalent of root privileges.

Don't get me wrong. I loved VMS back in the day. It was a pain in the
ass at times, but what isn't. It's just that it's not a VM trying to
execute byte-code... it's an operating system which directly manages
hardware.
Yeah, but don't forget that for all intents and purposes parrot is an 
OS trying to execute bytecode, especially when you look at the 
environments that the features will get used in.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A sketch of the security model

2005-04-14 Thread Dan Sugalski
At 9:51 AM -0700 4/14/05, Dave Whipp wrote:
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)
...
   * Number of open files
   * IO operations/sec
   * IO operations total
...
Can an application get more resources simply by spawning threads? 
If the answer is no, parent and child must divide share their 
quotas then there is a load balancing problem. If the answer is 
yes, then there's no real protection at all. A threads-per-second 
limit isn't an answer here, either (a malicious app could sit around 
for a few hours, launching threads at a low intensity, until it has 
enough to bring down the system).
Spawning threads may require a privilege, and there should be a quota 
for it, so the number of spawned threads could be managed.

I can see sharing quotas across multiple threads, though there are 
issues there (like sharing CPU time) as well.

Is a thread really the right thing to apply these limits to? It 
seems to me that there needs to be some sort of token (cf. cash; cf 
capability) that an application can obtain/spend/refresh to do 
these ops. An application could share its token(s) with any threads 
it creates. It could probably even loan its token to a backgroud 
thread that does some operation on behalf of many other threads.
Well, and interpreter is as fine-grained as we can get, and you're 
right, we may want to get a bit broader and share quotas amongst 
multiple threads. I don't know that we want to get much fancier than 
grouping threads together, though -- while I can see it being useful 
in a few cases, I'm not sure in practice that anyone'd actually want 
to do that.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A sketch of the security model

2005-04-14 Thread Aaron Sherman
On Thu, 2005-04-14 at 13:22 -0400, Dan Sugalski wrote:

 Anyway, a number of people I deeply respect (and who do this sort of 
 thing for a living, at deep levels) have told me flat-out that we're 
 better not having a security system than we are trying to roll our 
 own, and the common response to We're lifting VMS' has been Good. 
 Do that.

Well, if you were lifting VMS's security model, that would be fine, but
you're really not. You're lifting the idea of VMS's security model.

A security model is a many-fold thing (I've only so far discussed the
highest and most user-visible level because they are the bits most
applicable to Parrot). You're talking about cherry-picking certain bits
and re-designing the rest to fit.

I have NO PROBLEM with that, but I want to make sure that you don't
think this is the easy way to go. It's not. You're biting off a HUGE
amount of work, and your first 2 attempts will likely be utterly wrong
(if history is any guide, not because you're not smart and capable).

 I think it would be easier to start from scratch, personally. I
 understand your concerns, but I don't think you run any less risk by
 creating a new VM security model out of an OS security model than you do
 by creating a new one. They both create many opportunities to make a
 mistake.
 
 That's not been the general consensus I've seen from people doing 
 security research and implementation.

They both create many opportunities to make a mistake. Really. Go ask
the folks at Microsoft who lifted VMS for NT's security model, and
then go ask the folks at Sun who rolled their own with Java. Both have
had significant pain.

 If you really want to reduce the chances that you'll make a mistake,
 swipe the security model from JVM or CLR and start with that. At least
 those have been tested in the large, and map closer to what Parrot wants
 to do than VMS.
 
 The problem is twofold with those. First, there's some indications 
 that they're busted, 

They're not busted so much as in many places they have needed
significant work. I think that the general consensus right now is that
JVM is fairly well sorted out in 1.5, and CLR is moving along well.

I would say that at an infrastructure level they're both more than
sufficient models, and that's all you're going to lift anyway (unless
you were considering lifting code from mono, which I'm not sure is
workable license-wise).

 and second (and more importantly) they're both 
 very coarse-grained, and that leads to excessive privs being handed 
 out, which increases your exposure to damage. 

That's fine. Merging down either JVM or CLR's privs into a granularity
that you're happy with should work fine, and again, privs are only a
small part of the security model. If you want a better picture these
sources might be useful:

http://developer.intel.com/technology/itj/2003/volume07issue01/art05_security/vol7iss1_art05.pdf
http://java.sun.com/docs/books/security/
http://www.arctecgroup.net/ISB0705GP.pdf
http://www.arctecgroup.net/ISB0706GP.pdf
http://www.arctecgroup.net/ISB0707GP.pdf

 Don't get me wrong. I loved VMS back in the day. It was a pain in the
 ass at times, but what isn't. It's just that it's not a VM trying to
 execute byte-code... it's an operating system which directly manages
 hardware.
 
 Yeah, but don't forget that for all intents and purposes parrot is an 
 OS trying to execute bytecode, 

VMS security was interesting because it was one of the first systems to
substantially abstract the security of the system from the security of
the hardware. You don't get to touch hardware because you're user-land,
so you have a very different set of concerns. You do, however, have
roughly the same set of concerns as the JVM and CLR. That's why I
suggested them. If you don't like them, that's cool, I was only trying
to save those of you who have enough time to think about something as
large as security infrastructure some time and pain.

I don't have that kind of spare time, so I bow to your superior ability
to manage your schedule.




A sketch of the security model

2005-04-13 Thread Dan Sugalski
So here's what I was thinking of for Parrot's security and quota 
model. (Note that none of this is actually *implemented* yet...)

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)

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:

   * Number of open files
   * IO operations/sec
   * IO operations total
   * Memory allocated
   * CPU time consumed
   * Threads spawned
   * Sub-processes spawned total
   * Simultaneous sub-processes
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 
and/or quota checking. Once enabled code must have proper privileges 
to disable it again.

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.

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.

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.

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)

--
Dan
--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: A sketch of the security model

2005-04-13 Thread Aaron Sherman
On Wed, 2005-04-13 at 17:01, Dan Sugalski wrote:
 So here's what I was thinking of for Parrot's security and quota 
 model. (Note that none of this is actually *implemented* yet...)
[...]
 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)

VMS at least *is* a priv-based security model, but VMS privs are not
appropriate for parrot on the whole.

That said, it's been 10+ years since I've touched VMS, so pardon as I go
and Google the priv list

Privs that make sense for Parrot without change:

   ALL   Allow all privileges.
   DETACHCreate detached processes.
   EXQUOTA   Exceed resource quotas.
   SETPRVGrant a process any privilege.
   SHMEM Create or delete data structures in shared memory.
   SYSGBLCreate system global sections.
   SYSLCKRequest locks on system resources.

Privs that make no sense at all for Parrot (as far as I can tell):

   ACNT  Create a process for which no accounting is performed.
   BUGCHKMake bugcheck error log entries.
   CMEXECChange mode to Executive.
   CMKRNLChange mode to Kernel.
   DIAGNOSE  Issue diagnostic I/O requests.
   GRPNAMEnter names in the group logical name table.
   GRPPRVAllow access to files in the group and system
 categories.
   MOUNT Issue mount volume I/O requests.
   PHY_IOIssue physical I/O requests.
   PRMCEBCreate permanent common event flag clusters.
   PRMGBLCreate permanent global clusters.
   PSWAPMChange process swap mode.
   SHARE Assign a channel to a device.
   SYSNAMEnter names in the system logical name table.
   TMPMBXCreate temporary mailbox devices.
   VOLPROOverride protection on a volume.
   WORLD Control the execution of any process on the system.

Privs that could make sense, but have different meanings:

   ALLSPOOL  Allocate spooled devices.
This means you can create new handles
   ALTPRIIncrease the base execution priority for any process.
change to: Allow QUOTA modification
   BYPASSAccess resources without regard to UIC protection.
This means ignore my privs and just do it (default)
   GROUP Control execution of other processes in the same group.
This is interp-to-interp control (e.g. kill my sibling)
   LOG_IOIssue logical I/O requests.
if we assume that this means any handle I/O
   NETMBXCreate a network device.
This just means allocate any network resource (e.g. socket)
   OPER  Perform system operator functions.
In VMS this was fuzzy, and referred to any operation
that told the OS that it required OPER (like running
certain tools). I'm not sure what this means for
Parrot that BYPASS does not
   PFNMAPCreate or delete sections mapped by page frame.
Allocate new PMCs
   PRMMBXCreate permanent mailbox devices.
Create special files of any sort (e.g. POSIX fifo)
   SECURITY  Perform security-related functions.
?
   SYSPRVAccess resources as if the process has a system UIC.
?

Privs that do not exist in VMS:

NEWPBC  Execute new Parrot Byte Code at run-time
DEBUG   Perform operations only appropriate for a debugger
GCDOD   Directly manage GC/DOD behavior
NONREL  Create I/O handles from non-relative locaters
(e.g. open a rooted path; possibly applicable to
URI interpretation also)
DLOAD   Dynamically load binary objects
PLOAD   Dynamically load Parrot byte code (bypass NEWPBC)
This allows a PVM to load an existing PBC module and
execute it, but not to create its own PBC at run-time.
More...?

I think it would be easier to start from scratch, personally. I
understand your concerns, but I don't think you run any less risk by
creating a new VM security model out of an OS security model than you do
by creating a new one. They both create many opportunities to make a
mistake.

If you really want to reduce the chances that you'll make a mistake,
swipe the security model from JVM or CLR and start with that. At least
those have been tested in the large, and map closer to what Parrot wants
to do than VMS.

Don't get me wrong. I loved VMS back in the day. It was a pain in the
ass at times, but what isn't. It's just that it's not a VM trying to

Re: A sketch of the security model

2005-04-13 Thread Michael Walter
Dan,

On 4/13/05, Dan Sugalski [EMAIL PROTECTED] 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)
Just to get me back on track: Does this mean that when you spawn a
thread, a separate interpreter runs in/manages that thread, or
something else?

 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.

How can dropping a privilege for the duration of a (dynamic) scope be
implemented? Does this need to be implemented via a parrot intrinsic,
such as:

  without_privs(list_of_privs, code_to_be_run_without_these_privs);

..or is it possible to do so with the primitives you sketched out above?

 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.

Does the code marking a subroutines must have any other privilege than
the one it is marking the subroutine with?

 ... Non-continuation
 invokables (subs and methods) maintain the current set of privs, plus
 possibly adding the sub-specific privs.

Same for closures?

Regards,
Michael