diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
commit | 458120dd40db6b4df55a4e96b650e16798ef06a0 (patch) | |
tree | 8f82685be24fef97e715c6f5ca4c68d34d5074ee /sys/src/cmd/python/Doc/lib/librexec.tex | |
parent | 3a742c699f6806c1145aea5149bf15de15a0afd7 (diff) |
add hg and python
Diffstat (limited to 'sys/src/cmd/python/Doc/lib/librexec.tex')
-rw-r--r-- | sys/src/cmd/python/Doc/lib/librexec.tex | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/sys/src/cmd/python/Doc/lib/librexec.tex b/sys/src/cmd/python/Doc/lib/librexec.tex new file mode 100644 index 000000000..35619e636 --- /dev/null +++ b/sys/src/cmd/python/Doc/lib/librexec.tex @@ -0,0 +1,275 @@ +\section{\module{rexec} --- + Restricted execution framework} + +\declaremodule{standard}{rexec} +\modulesynopsis{Basic restricted execution framework.} +\versionchanged[Disabled module]{2.3} + +\begin{notice}[warning] + The documentation has been left in place to help in reading old code + that uses the module. +\end{notice} + +This module contains the \class{RExec} class, which supports +\method{r_eval()}, \method{r_execfile()}, \method{r_exec()}, and +\method{r_import()} methods, which are restricted versions of the standard +Python functions \method{eval()}, \method{execfile()} and +the \keyword{exec} and \keyword{import} statements. +Code executed in this restricted environment will +only have access to modules and functions that are deemed safe; you +can subclass \class{RExec} to add or remove capabilities as desired. + +\begin{notice}[warning] + While the \module{rexec} module is designed to perform as described + below, it does have a few known vulnerabilities which could be + exploited by carefully written code. Thus it should not be relied + upon in situations requiring ``production ready'' security. In such + situations, execution via sub-processes or very careful + ``cleansing'' of both code and data to be processed may be + necessary. Alternatively, help in patching known \module{rexec} + vulnerabilities would be welcomed. +\end{notice} + +\begin{notice} + The \class{RExec} class can prevent code from performing unsafe + operations like reading or writing disk files, or using TCP/IP + sockets. However, it does not protect against code using extremely + large amounts of memory or processor time. +\end{notice} + +\begin{classdesc}{RExec}{\optional{hooks\optional{, verbose}}} +Returns an instance of the \class{RExec} class. + +\var{hooks} is an instance of the \class{RHooks} class or a subclass of it. +If it is omitted or \code{None}, the default \class{RHooks} class is +instantiated. +Whenever the \module{rexec} module searches for a module (even a +built-in one) or reads a module's code, it doesn't actually go out to +the file system itself. Rather, it calls methods of an \class{RHooks} +instance that was passed to or created by its constructor. (Actually, +the \class{RExec} object doesn't make these calls --- they are made by +a module loader object that's part of the \class{RExec} object. This +allows another level of flexibility, which can be useful when changing +the mechanics of \keyword{import} within the restricted environment.) + +By providing an alternate \class{RHooks} object, we can control the +file system accesses made to import a module, without changing the +actual algorithm that controls the order in which those accesses are +made. For instance, we could substitute an \class{RHooks} object that +passes all filesystem requests to a file server elsewhere, via some +RPC mechanism such as ILU. Grail's applet loader uses this to support +importing applets from a URL for a directory. + +If \var{verbose} is true, additional debugging output may be sent to +standard output. +\end{classdesc} + +It is important to be aware that code running in a restricted +environment can still call the \function{sys.exit()} function. To +disallow restricted code from exiting the interpreter, always protect +calls that cause restricted code to run with a +\keyword{try}/\keyword{except} statement that catches the +\exception{SystemExit} exception. Removing the \function{sys.exit()} +function from the restricted environment is not sufficient --- the +restricted code could still use \code{raise SystemExit}. Removing +\exception{SystemExit} is not a reasonable option; some library code +makes use of this and would break were it not available. + + +\begin{seealso} + \seetitle[http://grail.sourceforge.net/]{Grail Home Page}{Grail is a + Web browser written entirely in Python. It uses the + \module{rexec} module as a foundation for supporting + Python applets, and can be used as an example usage of + this module.} +\end{seealso} + + +\subsection{RExec Objects \label{rexec-objects}} + +\class{RExec} instances support the following methods: + +\begin{methoddesc}{r_eval}{code} +\var{code} must either be a string containing a Python expression, or +a compiled code object, which will be evaluated in the restricted +environment's \module{__main__} module. The value of the expression or +code object will be returned. +\end{methoddesc} + +\begin{methoddesc}{r_exec}{code} +\var{code} must either be a string containing one or more lines of +Python code, or a compiled code object, which will be executed in the +restricted environment's \module{__main__} module. +\end{methoddesc} + +\begin{methoddesc}{r_execfile}{filename} +Execute the Python code contained in the file \var{filename} in the +restricted environment's \module{__main__} module. +\end{methoddesc} + +Methods whose names begin with \samp{s_} are similar to the functions +beginning with \samp{r_}, but the code will be granted access to +restricted versions of the standard I/O streams \code{sys.stdin}, +\code{sys.stderr}, and \code{sys.stdout}. + +\begin{methoddesc}{s_eval}{code} +\var{code} must be a string containing a Python expression, which will +be evaluated in the restricted environment. +\end{methoddesc} + +\begin{methoddesc}{s_exec}{code} +\var{code} must be a string containing one or more lines of Python code, +which will be executed in the restricted environment. +\end{methoddesc} + +\begin{methoddesc}{s_execfile}{code} +Execute the Python code contained in the file \var{filename} in the +restricted environment. +\end{methoddesc} + +\class{RExec} objects must also support various methods which will be +implicitly called by code executing in the restricted environment. +Overriding these methods in a subclass is used to change the policies +enforced by a restricted environment. + +\begin{methoddesc}{r_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} +Import the module \var{modulename}, raising an \exception{ImportError} +exception if the module is considered unsafe. +\end{methoddesc} + +\begin{methoddesc}{r_open}{filename\optional{, mode\optional{, bufsize}}} +Method called when \function{open()} is called in the restricted +environment. The arguments are identical to those of \function{open()}, +and a file object (or a class instance compatible with file objects) +should be returned. \class{RExec}'s default behaviour is allow opening +any file for reading, but forbidding any attempt to write a file. See +the example below for an implementation of a less restrictive +\method{r_open()}. +\end{methoddesc} + +\begin{methoddesc}{r_reload}{module} +Reload the module object \var{module}, re-parsing and re-initializing it. +\end{methoddesc} + +\begin{methoddesc}{r_unload}{module} +Unload the module object \var{module} (remove it from the +restricted environment's \code{sys.modules} dictionary). +\end{methoddesc} + +And their equivalents with access to restricted standard I/O streams: + +\begin{methoddesc}{s_import}{modulename\optional{, globals\optional{, + locals\optional{, fromlist}}}} +Import the module \var{modulename}, raising an \exception{ImportError} +exception if the module is considered unsafe. +\end{methoddesc} + +\begin{methoddesc}{s_reload}{module} +Reload the module object \var{module}, re-parsing and re-initializing it. +\end{methoddesc} + +\begin{methoddesc}{s_unload}{module} +Unload the module object \var{module}. +% XXX what are the semantics of this? +\end{methoddesc} + + +\subsection{Defining restricted environments \label{rexec-extension}} + +The \class{RExec} class has the following class attributes, which are +used by the \method{__init__()} method. Changing them on an existing +instance won't have any effect; instead, create a subclass of +\class{RExec} and assign them new values in the class definition. +Instances of the new class will then use those new values. All these +attributes are tuples of strings. + +\begin{memberdesc}{nok_builtin_names} +Contains the names of built-in functions which will \emph{not} be +available to programs running in the restricted environment. The +value for \class{RExec} is \code{('open', 'reload', '__import__')}. +(This gives the exceptions, because by far the majority of built-in +functions are harmless. A subclass that wants to override this +variable should probably start with the value from the base class and +concatenate additional forbidden functions --- when new dangerous +built-in functions are added to Python, they will also be added to +this module.) +\end{memberdesc} + +\begin{memberdesc}{ok_builtin_modules} +Contains the names of built-in modules which can be safely imported. +The value for \class{RExec} is \code{('audioop', 'array', 'binascii', +'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator', +'parser', 'regex', 'select', 'sha', '_sre', 'strop', +'struct', 'time')}. A similar remark about overriding this variable +applies --- use the value from the base class as a starting point. +\end{memberdesc} + +\begin{memberdesc}{ok_path} +Contains the directories which will be searched when an \keyword{import} +is performed in the restricted environment. +The value for \class{RExec} is the same as \code{sys.path} (at the time +the module is loaded) for unrestricted code. +\end{memberdesc} + +\begin{memberdesc}{ok_posix_names} +% Should this be called ok_os_names? +Contains the names of the functions in the \refmodule{os} module which will be +available to programs running in the restricted environment. The +value for \class{RExec} is \code{('error', 'fstat', 'listdir', +'lstat', 'readlink', 'stat', 'times', 'uname', 'getpid', 'getppid', +'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')}. +\end{memberdesc} + +\begin{memberdesc}{ok_sys_names} +Contains the names of the functions and variables in the \refmodule{sys} +module which will be available to programs running in the restricted +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} + +Let us say that we want a slightly more relaxed policy than the +standard \class{RExec} class. For example, if we're willing to allow +files in \file{/tmp} to be written, we can subclass the \class{RExec} +class: + +\begin{verbatim} +class TmpWriterRExec(rexec.RExec): + def r_open(self, file, mode='r', buf=-1): + if mode in ('r', 'rb'): + pass + elif mode in ('w', 'wb', 'a', 'ab'): + # check filename : must begin with /tmp/ + if file[:5]!='/tmp/': + raise IOError, "can't write outside /tmp" + elif (string.find(file, '/../') >= 0 or + file[:3] == '../' or file[-3:] == '/..'): + raise IOError, "'..' in filename forbidden" + else: raise IOError, "Illegal open() mode" + return open(file, mode, buf) +\end{verbatim} +% +Notice that the above code will occasionally forbid a perfectly valid +filename; for example, code in the restricted environment won't be +able to open a file called \file{/tmp/foo/../bar}. To fix this, the +\method{r_open()} method would have to simplify the filename to +\file{/tmp/bar}, which would require splitting apart the filename and +performing various operations on it. In cases where security is at +stake, it may be preferable to write simple code which is sometimes +overly restrictive, instead of more general code that is also more +complex and may harbor a subtle security hole. |