summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2002-05-31 21:19:53 +0000
committerGuido van Rossum <guido@python.org>2002-05-31 21:19:53 +0000
commit4d4a642a43c219417656f72f2ff650b96bf47917 (patch)
treed25cc5f269a4bb859114ba4635cf610c21812e94
parentc1976cbebd6b129ab13640e296a9e8690f034f8c (diff)
downloadcpython-4d4a642a43c219417656f72f2ff650b96bf47917.tar.gz
Backport to 2.1.x:
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).
-rw-r--r--Doc/lib/librexec.tex12
-rw-r--r--Lib/rexec.py12
2 files changed, 23 insertions, 1 deletions
diff --git a/Doc/lib/librexec.tex b/Doc/lib/librexec.tex
index 1f56a984b8..f00ddfcfc0 100644
--- a/Doc/lib/librexec.tex
+++ b/Doc/lib/librexec.tex
@@ -210,6 +210,18 @@ environment. The value for \class{RExec} is \code{('ps1', 'ps2',
'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 cb397ce75c..ccc53df03a 100644
--- a/Lib/rexec.py
+++ b/Lib/rexec.py
@@ -22,6 +22,7 @@ import sys
import __builtin__
import os
import ihooks
+import imp
__all__ = ["RExec"]
@@ -83,6 +84,9 @@ class RHooks(ihooks.Hooks):
# 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)
@@ -134,6 +138,8 @@ class RExec(ihooks._Verbose):
nok_builtin_names = ('open', 'reload', '__import__')
+ ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)
+
def __init__(self, hooks = None, verbose = 0):
ihooks._Verbose.__init__(self, verbose)
# XXX There's a circular reference here:
@@ -169,7 +175,6 @@ class RExec(ihooks._Verbose):
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
@@ -180,6 +185,11 @@ class RExec(ihooks._Verbose):
# 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