1 \section{\module{rexec
} ---
2 Restricted execution framework
}
4 \declaremodule{standard
}{rexec
}
5 \modulesynopsis{Basic restricted execution framework.
}
9 This module contains the
\class{RExec
} class, which supports
10 \method{r_eval()
},
\method{r_execfile()
},
\method{r_exec()
}, and
11 \method{r_import()
} methods, which are restricted versions of the standard
12 Python functions
\method{eval()
},
\method{execfile()
} and
13 the
\keyword{exec
} and
\keyword{import
} statements.
14 Code executed in this restricted environment will
15 only have access to modules and functions that are deemed safe; you
16 can subclass
\class{RExec
} to add or remove capabilities as desired.
18 \emph{Note:
} The
\class{RExec
} class can prevent code from performing
19 unsafe operations like reading or writing disk files, or using TCP/IP
20 sockets. However, it does not protect against code using extremely
21 large amounts of memory or CPU time.
23 \begin{classdesc
}{RExec
}{\optional{hooks
\optional{, verbose
}}}
24 Returns an instance of the
\class{RExec
} class.
26 \var{hooks
} is an instance of the
\class{RHooks
} class or a subclass of it.
27 If it is omitted or
\code{None
}, the default
\class{RHooks
} class is
29 Whenever the
\module{rexec
} module searches for a module (even a
30 built-in one) or reads a module's code, it doesn't actually go out to
31 the file system itself. Rather, it calls methods of an
\class{RHooks
}
32 instance that was passed to or created by its constructor. (Actually,
33 the
\class{RExec
} object doesn't make these calls --- they are made by
34 a module loader object that's part of the
\class{RExec
} object. This
35 allows another level of flexibility, e.g. using packages.)
37 By providing an alternate
\class{RHooks
} object, we can control the
38 file system accesses made to import a module, without changing the
39 actual algorithm that controls the order in which those accesses are
40 made. For instance, we could substitute an
\class{RHooks
} object that
41 passes all filesystem requests to a file server elsewhere, via some
42 RPC mechanism such as ILU. Grail's applet loader uses this to support
43 importing applets from a URL for a directory.
45 If
\var{verbose
} is true, additional debugging output may be sent to
49 It is important to be aware that code running in a restricted
50 environment can still call the
\function{sys.exit()
} function. To
51 disallow restricted code from exiting the interpreter, always protect
52 calls that cause restricted code to run with a
53 \keyword{try
}/
\keyword{except
} statement that catches the
54 \exception{SystemExit
} exception. Removing the
\function{sys.exit()
}
55 function from the restricted environment is not sufficient --- the
56 restricted code could still use
\code{raise SystemExit
}. Removing
57 \exception{SystemExit
} is not a reasonable option; some library code
58 makes use of this and would break were it not available.
62 \seetitle[http://grail.sourceforge.net/
]{Grail Home Page
}{Grail is a
63 Web browser written entirely in Python. It uses the
64 \module{rexec
} module as a foundation for supporting
65 Python applets, and can be used as an example usage of
70 \subsection{RExec Objects
\label{rexec-objects
}}
72 \class{RExec
} instances support the following methods:
74 \begin{methoddesc
}{r_eval
}{code
}
75 \var{code
} must either be a string containing a Python expression, or
76 a compiled code object, which will be evaluated in the restricted
77 environment's
\module{__main__
} module. The value of the expression or
78 code object will be returned.
81 \begin{methoddesc
}{r_exec
}{code
}
82 \var{code
} must either be a string containing one or more lines of
83 Python code, or a compiled code object, which will be executed in the
84 restricted environment's
\module{__main__
} module.
87 \begin{methoddesc
}{r_execfile
}{filename
}
88 Execute the Python code contained in the file
\var{filename
} in the
89 restricted environment's
\module{__main__
} module.
92 Methods whose names begin with
\samp{s_
} are similar to the functions
93 beginning with
\samp{r_
}, but the code will be granted access to
94 restricted versions of the standard I/O streams
\code{sys.stdin
},
95 \code{sys.stderr
}, and
\code{sys.stdout
}.
97 \begin{methoddesc
}{s_eval
}{code
}
98 \var{code
} must be a string containing a Python expression, which will
99 be evaluated in the restricted environment.
102 \begin{methoddesc
}{s_exec
}{code
}
103 \var{code
} must be a string containing one or more lines of Python code,
104 which will be executed in the restricted environment.
107 \begin{methoddesc
}{s_execfile
}{code
}
108 Execute the Python code contained in the file
\var{filename
} in the
109 restricted environment.
112 \class{RExec
} objects must also support various methods which will be
113 implicitly called by code executing in the restricted environment.
114 Overriding these methods in a subclass is used to change the policies
115 enforced by a restricted environment.
117 \begin{methoddesc
}{r_import
}{modulename
\optional{, globals
\optional{,
118 locals
\optional{, fromlist
}}}}
119 Import the module
\var{modulename
}, raising an
\exception{ImportError
}
120 exception if the module is considered unsafe.
123 \begin{methoddesc
}{r_open
}{filename
\optional{, mode
\optional{, bufsize
}}}
124 Method called when
\function{open()
} is called in the restricted
125 environment. The arguments are identical to those of
\function{open()
},
126 and a file object (or a class instance compatible with file objects)
127 should be returned.
\class{RExec
}'s default behaviour is allow opening
128 any file for reading, but forbidding any attempt to write a file. See
129 the example below for an implementation of a less restrictive
133 \begin{methoddesc
}{r_reload
}{module
}
134 Reload the module object
\var{module
}, re-parsing and re-initializing it.
137 \begin{methoddesc
}{r_unload
}{module
}
138 Unload the module object
\var{module
} (i.e., remove it from the
139 restricted environment's
\code{sys.modules
} dictionary).
142 And their equivalents with access to restricted standard I/O streams:
144 \begin{methoddesc
}{s_import
}{modulename
\optional{, globals
\optional{,
145 locals
\optional{, fromlist
}}}}
146 Import the module
\var{modulename
}, raising an
\exception{ImportError
}
147 exception if the module is considered unsafe.
150 \begin{methoddesc
}{s_reload
}{module
}
151 Reload the module object
\var{module
}, re-parsing and re-initializing it.
154 \begin{methoddesc
}{s_unload
}{module
}
155 Unload the module object
\var{module
}.
156 % XXX what are the semantics of this?
160 \subsection{Defining restricted environments
\label{rexec-extension
}}
162 The
\class{RExec
} class has the following class attributes, which are
163 used by the
\method{__init__()
} method. Changing them on an existing
164 instance won't have any effect; instead, create a subclass of
165 \class{RExec
} and assign them new values in the class definition.
166 Instances of the new class will then use those new values. All these
167 attributes are tuples of strings.
169 \begin{memberdesc
}{nok_builtin_names
}
170 Contains the names of built-in functions which will
\emph{not
} be
171 available to programs running in the restricted environment. The
172 value for
\class{RExec
} is
\code{('open', 'reload', '__import__')
}.
173 (This gives the exceptions, because by far the majority of built-in
174 functions are harmless. A subclass that wants to override this
175 variable should probably start with the value from the base class and
176 concatenate additional forbidden functions --- when new dangerous
177 built-in functions are added to Python, they will also be added to
181 \begin{memberdesc
}{ok_builtin_modules
}
182 Contains the names of built-in modules which can be safely imported.
183 The value for
\class{RExec
} is
\code{('audioop', 'array', 'binascii',
184 'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator',
185 'parser', 'regex', 'rotor', 'select', 'strop', 'struct', 'time')
}. A
186 similar remark about overriding this variable applies --- use the
187 value from the base class as a starting point.
190 \begin{memberdesc
}{ok_path
}
191 Contains the directories which will be searched when an
\keyword{import
}
192 is performed in the restricted environment.
193 The value for
\class{RExec
} is the same as
\code{sys.path
} (at the time
194 the module is loaded) for unrestricted code.
197 \begin{memberdesc
}{ok_posix_names
}
198 % Should this be called ok_os_names?
199 Contains the names of the functions in the
\refmodule{os
} module which will be
200 available to programs running in the restricted environment. The
201 value for
\class{RExec
} is
\code{('error', 'fstat', 'listdir',
202 'lstat', 'readlink', 'stat', 'times', 'uname', 'getpid', 'getppid',
203 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')
}.
206 \begin{memberdesc
}{ok_sys_names
}
207 Contains the names of the functions and variables in the
\refmodule{sys
}
208 module which will be available to programs running in the restricted
209 environment. The value for
\class{RExec
} is
\code{('ps1', 'ps2',
210 'copyright', 'version', 'platform', 'exit', 'maxint')
}.
214 \subsection{An example
}
216 Let us say that we want a slightly more relaxed policy than the
217 standard
\class{RExec
} class. For example, if we're willing to allow
218 files in
\file{/tmp
} to be written, we can subclass the
\class{RExec
}
222 class TmpWriterRExec(rexec.RExec):
223 def r_open(self, file, mode='r', buf=-
1):
224 if mode in ('r', 'rb'):
226 elif mode in ('w', 'wb', 'a', 'ab'):
227 # check filename : must begin with /tmp/
228 if file
[:
5]!='/tmp/':
229 raise IOError, "can't write outside /tmp"
230 elif (string.find(file, '/../') >=
0 or
231 file
[:
3] == '../' or file
[-
3:
] == '/..'):
232 raise IOError, "'..' in filename forbidden"
233 else: raise IOError, "Illegal open() mode"
234 return open(file, mode, buf)
237 Notice that the above code will occasionally forbid a perfectly valid
238 filename; for example, code in the restricted environment won't be
239 able to open a file called
\file{/tmp/foo/../bar
}. To fix this, the
240 \method{r_open()
} method would have to simplify the filename to
241 \file{/tmp/bar
}, which would require splitting apart the filename and
242 performing various operations on it. In cases where security is at
243 stake, it may be preferable to write simple code which is sometimes
244 overly restrictive, instead of more general code that is also more
245 complex and may harbor a subtle security hole.