[IronPython] Restricting IronPython

Jeff Brown Jeff at ingenio.com
Fri Apr 6 23:14:09 PDT 2007

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...


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




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



-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ironpython.com/pipermail/users-ironpython.com/attachments/20070406/03023dd2/attachment.htm 

More information about the users mailing list