[IronPython] Restricting IronPython

Markus Hajek markus.hajek at teamvienna.at
Thu Apr 12 09:32:15 CEST 2007


Hi,

 

thank you for your thoughts. CAS sure enough is a valuable addition to my
arsenal for keeping designer's code in their sandbox (even though I do not
expect them to actively try a DOS-attack, but innocents can sometimes cause
the most harm ;-)

 

CAS wouldn't help to prevent the time-problem, though. And the
Thread.Abort() way of ensuring that Python-code doesn't execute too long
just does not seem very stable.

Ideally, I'd like to be able to interrupt python execution with each python
statement. I do not need to interrupt inside a python statement because a
single statement cannot execute very long except for when it calls library
code. As the only library code I expose to Python is under my control, I can
guarantee this code to not expose any methods with inacceptable
runtime-behavior. Alas, I have not yet found out where I could add such
behavior (see my other mail).

 

Interestingly, I have been looking for a ready-made sandbox environment, but
with no success. Actually, I'm also somewhat surprised that it seems as if
I'm the first wanting to use IronPython in such a way, given the history of
CPython being used for game-scripting languages. 

 

Cheers,

 

Markus Hajek

Team Vienna - Kazemi, Hajek & Pisarik OG

 

Von: users-bounces at lists.ironpython.com
[mailto:users-bounces at lists.ironpython.com] Im Auftrag von Jeff Brown
Gesendet: Samstag, 07. April 2007 08:14
An: Discussion of IronPython
Betreff: Re: [IronPython] Restricting IronPython

 

You'll want to apply CodeAccessSecurity constraints to limit access to
various pieces of functionality like Assembly.Load, etc...

 

Basically, before you run any of this "untrusted" code, you should enter a
minimum security context that specifically does not have permission to
access the filesystem, run native code, link to other libraries and whatnot.
It should only be able to do relatively "safe" things that prevent the code
from exiting the .Net sandbox.  In your own game libraries, you'll want to
ensure that your methods can be called from a Partially Trusted context and
can Demand the necessary priviledges to run.  However, be aware that locking
up the CPU is just one of many denial of service techniques a malicious (or
careless) game user or designer might employ.  Such a user might also cause
log files to pile up, cause stack overflows, generate unreasonable network
traffic, cause huge numbers of exceptions to be thrown, allocate large
numbers of objects, leak memory and so on.  CodeAccessSecurity will really
cut down on how much of this can be done by user code, but you do need to
very careful when you write your library to ensure that none of its
functions can be abused (even innocently!).

 

In any case, assuming you deny the SecurityPermissionFlag.ControlThread
permission, then you can use Thread.Abort() to kill the thread.  As Dino
suggested you set up a monitoring thread that enforces the quantum and calls
Thread.Abort().  If the code that's running does not have ControlThread (and
can't block in unusual ways) then it cannot call Thread.ResetAbort() to
prevent its shutdown.  It _should_ shut down pretty quickly.  I wouldn't be
surprised if using Thread.Abort() were not completely robust but doing it
within .Net (instead of via native code as I think Dino implies) is at least
guaranteed not to trash the runtime environment.

 

You might be interested in the constrained execution model that was added to
.Net 2.0 to support integration with the CLR.  It specifies that only code
that satisfies certain reliability contracts may run.  Check out this
article: http://msdn2.microsoft.com/en-us/library/ms228973.aspx  It doesn't
sound like you need to be quite that paranoid though.

 

Someone out there must have already implemented a robust .Net sandbox for
just the kind of thing you're trying to do...  Look around.  It may be hard
to find something that will work with IronPython because it uses a lot of
reflection and its builtin modules might not be completely safe w.r.t.
CodeAccessSecurity (might expose dangerous public methods).  I'm just
guessing here...

 

Jeff.

 

  _____  

From: users-bounces at lists.ironpython.com
[mailto:users-bounces at lists.ironpython.com] On Behalf Of Dino Viehland
Sent: Friday, April 06, 2007 2:43 PM
To: Discussion of IronPython
Subject: Re: [IronPython] Restricting IronPython

There's two ways I can think of how to enforce the time limit:

1.       An external monitor which aborts the thread when a quantum has
expired.  This has the problem of potentially aborting at any native CPU
instruction which most code is in no way prepared to handle.  Therefore 

2.       Update CodeGen to emit checks to see if the current quantum has
expired.  Most likely you'd want to do this on every back-branch within the
IL.  I'm not sure how exactly you'd detect that w/o putting an abstraction
around the Label structure so you know where each label lives within the IL.
For compiler generated loops which you know to be bounded you could
eliminate the check also and only do it for user defined loops.

 

 

From: users-bounces at lists.ironpython.com
[mailto:users-bounces at lists.ironpython.com] On Behalf Of Markus Hajek
Sent: Friday, April 06, 2007 6:33 AM
To: users at lists.ironpython.com
Subject: [IronPython] Restricting IronPython

 

Hi,

 

I'm evaluating IronPython for use as a scripting language in a game server.
Designers would use it for game-logic.

 

Because designers typically are not engineers, one cannot expect them to
follow common good practices. So I need to restrict what their script code
can do in a few ways:

a.       They should not be able to use any libraries other than what we
expose to them explicitly. That includes Python libraries (other than local)
and .NET-Framework libraries.

b.      For framework classes it's necessary to expose only certain members
of these classes that are meant to be used from Python.

c.       It should be possible to time-limit execution time of a script.
Designers might build scripts that under certain circumstances enter an
infinite loop or something similar. In such a case, script execution should
be aborted.

 

Now with a) it's easy enough to take away access to Python libraries.
Neither is there a problem with .NET framework stuff because you need to add
a reference explicitly - with two exceptions, mscorlib.dll and system.dll
are referenced automatically. I wrote a patch to get around this
(PythonEngine and ReflectedPackage). With this patch you have two boolean
properties in EngineOptions, AutoReferenceMscorlib and AutoReferenceSystem
which by default are set to true to keep behavior as it is, but can be set
to false, too, with the expected effect.

 

For b) it turns out there is no easy way of having a framework classes
expose only certain methods/properties by for example passing only an
interface to Python. That just doesn't work because Python will allow access
to any public member of the concrete instance. One way around that would be
to write adapter for each framework class (like: for class Player create
class PythonPlayer which holds an instance of Player as private member and
exposes only those members publicly that should be visible from Python), but
that would be tedious. So I created another patch (Attributes and
ReflectedType) which adds a new attribute [DoNotExpose] to IronPython.
Framework code writers can decorate properties, methods, fields, nested
types etc. with this attribute. Members decorated such won't be visible to
Python code. Again, by default behavior is not changed as no code has this
attribute.

 

With c) I am stuck. I'm not at all sure where I could add such functionality
with minimum impact to the existing codebase.

 

Any ideas on that?

 

Besides, any feedback to the patches would be most welcome, too.

 

Happy Easter holidays,

 

Max Hajek

Vienna

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20070412/519c443b/attachment.html>


More information about the Ironpython-users mailing list