SF bug 533625 (Armin Rigo). rexec: potential security hole

If a rexec instance allows writing in the current directory (a common
thing to do), there's a way to execute bogus bytecode.  Fix this by
not allowing imports from .pyc files (in a way that allows a site to
configure things so that .pyc files *are* allowed, if writing is not
allowed).

I'll apply this to 2.2 and 2.1 too.
diff --git a/Doc/lib/librexec.tex b/Doc/lib/librexec.tex
index 6184a48..ff6cdc4 100644
--- a/Doc/lib/librexec.tex
+++ b/Doc/lib/librexec.tex
@@ -211,6 +211,18 @@
 'copyright', 'version', 'platform', 'exit', 'maxint')}.
 \end{memberdesc}
 
+\begin{memberdesc}{ok_file_types}
+Contains the file types from which modules are allowed to be loaded.
+Each file type is an integer constant defined in the \refmodule{imp} module.
+The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and
+\constant{C_EXTENSION}.  The value for \class{RExec} is \code{(C_EXTENSION,
+PY_SOURCE)}.  Adding \constant{PY_COMPILED} in subclasses is not recommended;
+an attacker could exit the restricted execution mode by putting a forged
+byte-compiled file (\file{.pyc}) anywhere in your file system, for example
+by writing it to \file{/tmp} or uploading it to the \file{/incoming}
+directory of your public FTP server.
+\end{memberdesc}
+
 
 \subsection{An example}
 
diff --git a/Lib/rexec.py b/Lib/rexec.py
index 7a239bc..04ff405 100644
--- a/Lib/rexec.py
+++ b/Lib/rexec.py
@@ -22,6 +22,7 @@
 import __builtin__
 import os
 import ihooks
+import imp
 
 __all__ = ["RExec"]
 
@@ -83,6 +84,9 @@
         # Called by RExec instance to complete initialization
         self.rexec = rexec
 
+    def get_suffixes(self):
+        return self.rexec.get_suffixes()
+
     def is_builtin(self, name):
         return self.rexec.is_builtin(name)
 
@@ -144,6 +148,8 @@
 
     nok_builtin_names = ('open', 'file', 'reload', '__import__')
 
+    ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)
+
     def __init__(self, hooks = None, verbose = 0):
         """Returns an instance of the RExec class.
 
@@ -203,7 +209,6 @@
         if sys.modules.has_key(name):
             src = sys.modules[name]
         else:
-            import imp
             src = imp.load_dynamic(name, filename, file)
         dst = self.copy_except(src, [])
         return dst
@@ -214,6 +219,11 @@
 
     # Helpers for RHooks
 
+    def get_suffixes(self):
+        return [item   # (suff, mode, type)
+                for item in imp.get_suffixes()
+                if item[2] in self.ok_file_types]
+
     def is_builtin(self, mname):
         return mname in self.ok_builtin_modules