blob: 32a565fdbeea34b5eee30263329efd396e9f1bfd [file] [log] [blame]
Guido van Rossumbe0a8a61996-09-10 17:37:05 +00001\section{Standard Module \sectcode{rexec}}
2\stmodindex{rexec}
3\renewcommand{\indexsubitem}{(in module rexec)}
4
Guido van Rossum095538d1996-10-22 01:11:19 +00005This module contains the \code{RExec} class, which supports
6\code{r_exec()}, \code{r_eval()}, \code{r_execfile()}, and
7\code{r_import()} methods, which are restricted versions of the standard
8Python functions \code{exec()}, \code{eval()}, \code{execfile()}, and
9\code{import()}. Code executed in this restricted environment will
10only have access to modules and functions that are deemed safe; you
11can subclass \code{RExec} to add or remove capabilities as desired.
12
13\emph{Note:} The \code{RExec} class can prevent code from performing
14unsafe operations like reading or writing disk files, or using TCP/IP
15sockets. However, it does not protect against code using extremely
16large amounts of memory or CPU time.
17% XXX is there any protection against this?
18
19\begin{funcdesc}{RExec}{\optional{hooks\, verbose} }
20Returns an instance of the \code{RExec} class.
21
22% XXX is ihooks.py documented? If yes, there should be a ref here
23
24\var{hooks} is an instance of the \code{RHooks} class or a subclass of it.
25Whenever the RExec module searches for a module (even a built-in one)
26or reads a module's code, it doesn't actually go out to the file
27system itself. Rather, it calls methods of an RHooks instance that
28was passed to or created by its constructor. (Actually, the RExec
29object doesn't make these calls---they are made by a module loader
30object that's part of the RExec object. This allows another level of
31flexibility, e.g. using packages.)
32
33By providing an alternate RHooks object, we can control the actual
34file system accesses made to import a module, without changing the
35actual algorithm that controls the order in which those accesses are
36made. For instance, we could substitute an RHooks object that passes
37all filesystem requests to a file server elsewhere, via some RPC
38mechanism such as ILU. Grail's applet loader uses this to support
39importing applets from a URL for a directory.
40
41% XXX does verbose actually do anything at the moment?
42If \var{verbose} is true, additional debugging output will be sent to
43standard output.
44\end{funcdesc}
45
46RExec instances have the following attributes, which are used by the
47\code{__init__} method. Changing them on an existing instance won't
48have any effect; instead, create a subclass of \code{RExec} and assign
49them new values in the class definition. Instances of the new class
50will then use those new values. All these attributes are tuples of
51strings.
52
53\renewcommand{\indexsubitem}{(RExec object attribute)}
54\begin{datadesc}{nok_builtin_names}
55Contains the names of built-in functions which will \emph{not} be
56 available to programs running in the restricted environment. The
57 value for \code{RExec} is \code{('open',} \code{reload',}
58 \code{__import__')}.
59\end{datadesc}
60
61\begin{datadesc}{ok_builtin_modules}
62Contains the names of built-in modules which can be safely imported.
63The value for \code{RExec} is \code{('array',} \code{'binascii',} \code{'audioop',}
64\code{'imageop',} \code{'marshal',} \code{'math',} \code{'md5',} \code{'parser',} \code{'regex',} \code{'rotor',}
65\code{'select',} \code{'strop',} \code{'struct',} \code{'time')}.
66\end{datadesc}
67
68\begin{datadesc}{ok_path}
69Contains the directories which will be searched when an \code{import}
70is performed in the restricted environment.
71The value for \code{RExec} is the same as \code{sys.path} for
72unrestricted code.
73\end{datadesc}
74
75\begin{datadesc}{ok_posix_names}
76% Should this be called ok_os_names?
77Contains the names of the functions in the \code{os} module which will be
78available to programs running in the restricted environment. The
79value for \code{RExec} is \code{('error',} \code{'fstat',}
80\code{'listdir',} \code{'lstat',} \code{'readlink',} \code{'stat',}
81\code{'times',} \code{'uname',} \code{'getpid',} \code{'getppid',}
82\code{'getcwd',} \code{'getuid',} \code{'getgid',} \code{'geteuid',}
83\code{'getegid')}.
84\end{datadesc}
85
86\begin{datadesc}{ok_sys_names}
87Contains the names of the functions and variables in the \code{sys} module which will be
88available to programs running in the restricted environment. The
89value for \code{RExec} is \code{('ps1',} \code{'ps2',}
90\code{'copyright',} \code{'version',} \code{'platform',} \code{'exit',}
91\code{'maxint')}.
92\end{datadesc}
93
94RExec instances support the following methods:
95\renewcommand{\indexsubitem}{(RExec object method)}
96
97\begin{funcdesc}{r_eval}{code}
98\var{code} must either be a string containing a Python expression, or a compiled code object, which will
99be evaluated in the restricted environment. The value of the expression or code object will be returned.
100\end{funcdesc}
101
102\begin{funcdesc}{r_exec}{code}
103\var{code} must either be a string containing one or more lines of Python code, or a compiled code object,
104which will be executed in the restricted environment.
105\end{funcdesc}
106
107\begin{funcdesc}{r_execfile}{filename}
108Execute the Python code contained in the file \var{filename} in the
109restricted environment.
110\end{funcdesc}
111
112Methods whose names begin with \code{s_} are similar to the functions
113beginning with \code{r_}, but the code will be granted access to
114restricted versions of \code{sys.stdin}, \code{sys.stderr}, and
115\code{sys.stdout}.
116
117\begin{funcdesc}{s_eval}{code}
118\var{code} must be a string containing a Python expression, which will
119be evaluated in the restricted environment.
120\end{funcdesc}
121
122\begin{funcdesc}{s_exec}{code}
123\var{code} must be a string containing one or more lines of Python code,
124which will be executed in the restricted environment.
125\end{funcdesc}
126
127\begin{funcdesc}{s_execfile}{code}
128Execute the Python code contained in the file \var{filename} in the
129restricted environment.
130\end{funcdesc}
131
132\code{RExec} objects must also support various methods which will be implicitly called
133by code executing in the restricted environment. Overriding these
134methods in a subclass is used to change the policies enforced by a restricted environment.
135
136\begin{funcdesc}{r_import}{modulename\optional{\, globals, locals, fromlist}}
137Import the module \var{modulename}, raising an \code{ImportError} exception
138if the module is considered unsafe.
139\end{funcdesc}
140
141\begin{funcdesc}{r_open}{filename\optional{\, mode\optional{\, bufsize}}}
142Method called when \code{open()} is called in the restricted
143environment. The arguments are identical to those of \code{open()},
144and a file object (or a class instance compatible with file objects)
145should be returned. \code{RExec}'s default behaviour is allow opening
146any file for reading, but forbidding any attempt to write a file. See
147the example below for an implementation of a less restrictive \code{r_open()}.
148\end{funcdesc}
149
150\begin{funcdesc}{r_reload}{module}
151Reload the module object \var{module}, re-parsing and re-initializing it.
152\end{funcdesc}
153
154\begin{funcdesc}{r_unload}{module}
155Unload the module object \var{module}.
156% XXX what are the semantics of this?
157\end{funcdesc}
158
159\begin{funcdesc}{s_import}{modulename\optional{\, globals, locals, fromlist}}
160Import the module \var{modulename}, raising an \code{ImportError} exception
161if the module is considered unsafe.
162\end{funcdesc}
163
164\begin{funcdesc}{s_reload}{module}
165Reload the module object \var{module}, re-parsing and re-initializing it.
166\end{funcdesc}
167
168\begin{funcdesc}{s_unload}{module}
169Unload the module object \var{module}.
170% XXX what are the semantics of this?
171\end{funcdesc}
172
173\subsection{An example}
174
175Let us say that we want a slightly more relaxed policy than the
176standard RExec class. For example, if we're willing to allow files in
177\file{/tmp} to be written, we can subclass the \code{RExec} class:
178
179\bcode\begin{verbatim}
180class TmpWriterRExec(rexec.RExec):
181 def r_open(self, file, mode='r', buf=-1):
182 if mode in ('r', 'rb'): pass
183 elif mode in ('w', 'wb'):
184 # check filename : must begin with /tmp/
185 if file[0:5]!='/tmp/':
186 raise IOError, "can't open files for writing outside of /tmp"
187 elif string.find(file, '/../')!=-1:
188 raise IOError, "'..' in filename; open for writing forbidden"
189 return open(file, mode, buf)
190\end{verbatim}\ecode
191
192Notice that the above code will occasionally forbid a perfectly valid
193filename; for example, code in the restricted environment won't be
194able to open a file called \file{/tmp/foo/../bar}. To fix this, the
195\code{r_open} method would have to simplify the filename to
196\file{/tmp/bar}, which would require splitting apart the filename and
197performing various operations on it. In cases where security is at
198stake, it may be preferable to write simple code which is sometimes
199overly restrictive, instead of more general code that is also more
200complex and may harbor a subtle security hole.