Looking for ideas on controlling python module loading

Chris Angelico rosuav at gmail.com
Sun Apr 3 21:03:07 EDT 2011


On Mon, Apr 4, 2011 at 10:44 AM, Nathan Coulson <conathan at gmail.com> wrote:
> Hello, I am working on a client/server program (game) that uses C w/
> an embedded python interpreter, that uses python to script what
> objects do in the game.   (primarily a C environment)
>
> I was wondering if it is possible to control what modules get loaded
> (or not).  perhaps by determining if the hash of the local file
> matches a hash provided by the server.
>
> I was also wondering, if you could construct a module, without a .py
> file, and define functions and variables.

You certainly can. I assume your idea is that you write the C code,
but someone else can write the Python, and you want to lock it down?
That's what I have in this system at work, and it's fairly easy to
sandbox.

(Note: This uses Python 2. Some things may be different in Python 3.)

There's three easy ways to set up the global dictionary:
1) py_globals=PyDict_New(); //Completely empty, not very useful. You
don't even get stuff like 'True' unless you manually add them.
2) py_globals=PyModule_GetDict(PyImport_AddModule("__main__")); //This
gives an environment similar to IDLE. Fairly wide open.
3) py_globals=PyModule_GetDict(PyImport_AddModule("__builtin__"));
//Restricted environment.

Go with the third option and you get easy control over what the Python
code can do. I then disable a number of functions with
PyDict_DelItemString (for instance, input and raw_input - my program
has no console); you could alternatively replace those symbols with
something of your own (maybe replace raw_input with something that
reads from the socket??), or leave them if they're not going to be a
problem.

What I did was to disable importing altogether, and import a specific
set of modules (math, string, and a couple more) manually. That
ensures that, no matter what, the sandbox is safe; but this might not
be well suited to your situation.

As to creating modules - I've never done that per se, but it's easy
enough to create a Py-callable function inside your C code. In what I
do, it's easier to simply insert that into the globals dictionary,
making it a top-level function:

PyMethodDef fnc={"functionname",functionname,1,"Function Description"};
PyDict_SetItemString(py_globals,"functionname",PyCFunction_New(&fnc,0));

Note by the way that I "cheat" the refcounting a bit with this
initialization code, since it is only ever called once and then the
global state is maintained through the whole program. If you need
multiple states or need to clean up the mess at some point, you may
need to check the refcounts to make sure none are leaked.

Hope that's of value!

Chris Angelico



More information about the Python-list mailing list