~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Doc/library/rexec.rst

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
:mod:`rexec` --- Restricted execution framework
 
3
===============================================
 
4
 
 
5
.. module:: rexec
 
6
   :synopsis: Basic restricted execution framework.
 
7
   :deprecated:
 
8
   
 
9
.. deprecated:: 2.6
 
10
   The :mod:`rexec` module has been removed in Python 3.0.
 
11
 
 
12
.. versionchanged:: 2.3
 
13
   Disabled module.
 
14
 
 
15
.. warning::
 
16
 
 
17
   The documentation has been left in place to help in reading old code that uses
 
18
   the module.
 
19
 
 
20
This module contains the :class:`RExec` class, which supports :meth:`r_eval`,
 
21
:meth:`r_execfile`, :meth:`r_exec`, and :meth:`r_import` methods, which are
 
22
restricted versions of the standard Python functions :meth:`eval`,
 
23
:meth:`execfile` and the :keyword:`exec` and :keyword:`import` statements. Code
 
24
executed in this restricted environment will only have access to modules and
 
25
functions that are deemed safe; you can subclass :class:`RExec` to add or remove
 
26
capabilities as desired.
 
27
 
 
28
.. warning::
 
29
 
 
30
   While the :mod:`rexec` module is designed to perform as described below, it does
 
31
   have a few known vulnerabilities which could be exploited by carefully written
 
32
   code.  Thus it should not be relied upon in situations requiring "production
 
33
   ready" security.  In such situations, execution via sub-processes or very
 
34
   careful "cleansing" of both code and data to be processed may be necessary.
 
35
   Alternatively, help in patching known :mod:`rexec` vulnerabilities would be
 
36
   welcomed.
 
37
 
 
38
.. note::
 
39
 
 
40
   The :class:`RExec` class can prevent code from performing unsafe operations like
 
41
   reading or writing disk files, or using TCP/IP sockets.  However, it does not
 
42
   protect against code using extremely large amounts of memory or processor time.
 
43
 
 
44
 
 
45
.. class:: RExec([hooks[, verbose]])
 
46
 
 
47
   Returns an instance of the :class:`RExec` class.
 
48
 
 
49
   *hooks* is an instance of the :class:`RHooks` class or a subclass of it. If it
 
50
   is omitted or ``None``, the default :class:`RHooks` class is instantiated.
 
51
   Whenever the :mod:`rexec` module searches for a module (even a built-in one) or
 
52
   reads a module's code, it doesn't actually go out to the file system itself.
 
53
   Rather, it calls methods of an :class:`RHooks` instance that was passed to or
 
54
   created by its constructor.  (Actually, the :class:`RExec` object doesn't make
 
55
   these calls --- they are made by a module loader object that's part of the
 
56
   :class:`RExec` object.  This allows another level of flexibility, which can be
 
57
   useful when changing the mechanics of :keyword:`import` within the restricted
 
58
   environment.)
 
59
 
 
60
   By providing an alternate :class:`RHooks` object, we can control the file system
 
61
   accesses made to import a module, without changing the actual algorithm that
 
62
   controls the order in which those accesses are made.  For instance, we could
 
63
   substitute an :class:`RHooks` object that passes all filesystem requests to a
 
64
   file server elsewhere, via some RPC mechanism such as ILU.  Grail's applet
 
65
   loader uses this to support importing applets from a URL for a directory.
 
66
 
 
67
   If *verbose* is true, additional debugging output may be sent to standard
 
68
   output.
 
69
 
 
70
It is important to be aware that code running in a restricted environment can
 
71
still call the :func:`sys.exit` function.  To disallow restricted code from
 
72
exiting the interpreter, always protect calls that cause restricted code to run
 
73
with a :keyword:`try`/:keyword:`except` statement that catches the
 
74
:exc:`SystemExit` exception.  Removing the :func:`sys.exit` function from the
 
75
restricted environment is not sufficient --- the restricted code could still use
 
76
``raise SystemExit``.  Removing :exc:`SystemExit` is not a reasonable option;
 
77
some library code makes use of this and would break were it not available.
 
78
 
 
79
 
 
80
.. seealso::
 
81
 
 
82
   `Grail Home Page <http://grail.sourceforge.net/>`_
 
83
      Grail is a Web browser written entirely in Python.  It uses the :mod:`rexec`
 
84
      module as a foundation for supporting Python applets, and can be used as an
 
85
      example usage of this module.
 
86
 
 
87
 
 
88
.. _rexec-objects:
 
89
 
 
90
RExec Objects
 
91
-------------
 
92
 
 
93
:class:`RExec` instances support the following methods:
 
94
 
 
95
 
 
96
.. method:: RExec.r_eval(code)
 
97
 
 
98
   *code* must either be a string containing a Python expression, or a compiled
 
99
   code object, which will be evaluated in the restricted environment's
 
100
   :mod:`__main__` module.  The value of the expression or code object will be
 
101
   returned.
 
102
 
 
103
 
 
104
.. method:: RExec.r_exec(code)
 
105
 
 
106
   *code* must either be a string containing one or more lines of Python code, or a
 
107
   compiled code object, which will be executed in the restricted environment's
 
108
   :mod:`__main__` module.
 
109
 
 
110
 
 
111
.. method:: RExec.r_execfile(filename)
 
112
 
 
113
   Execute the Python code contained in the file *filename* in the restricted
 
114
   environment's :mod:`__main__` module.
 
115
 
 
116
Methods whose names begin with ``s_`` are similar to the functions beginning
 
117
with ``r_``, but the code will be granted access to restricted versions of the
 
118
standard I/O streams ``sys.stdin``, ``sys.stderr``, and ``sys.stdout``.
 
119
 
 
120
 
 
121
.. method:: RExec.s_eval(code)
 
122
 
 
123
   *code* must be a string containing a Python expression, which will be evaluated
 
124
   in the restricted environment.
 
125
 
 
126
 
 
127
.. method:: RExec.s_exec(code)
 
128
 
 
129
   *code* must be a string containing one or more lines of Python code, which will
 
130
   be executed in the restricted environment.
 
131
 
 
132
 
 
133
.. method:: RExec.s_execfile(code)
 
134
 
 
135
   Execute the Python code contained in the file *filename* in the restricted
 
136
   environment.
 
137
 
 
138
:class:`RExec` objects must also support various methods which will be
 
139
implicitly called by code executing in the restricted environment. Overriding
 
140
these methods in a subclass is used to change the policies enforced by a
 
141
restricted environment.
 
142
 
 
143
 
 
144
.. method:: RExec.r_import(modulename[, globals[, locals[, fromlist]]])
 
145
 
 
146
   Import the module *modulename*, raising an :exc:`ImportError` exception if the
 
147
   module is considered unsafe.
 
148
 
 
149
 
 
150
.. method:: RExec.r_open(filename[, mode[, bufsize]])
 
151
 
 
152
   Method called when :func:`open` is called in the restricted environment.  The
 
153
   arguments are identical to those of :func:`open`, and a file object (or a class
 
154
   instance compatible with file objects) should be returned.  :class:`RExec`'s
 
155
   default behaviour is allow opening any file for reading, but forbidding any
 
156
   attempt to write a file.  See the example below for an implementation of a less
 
157
   restrictive :meth:`r_open`.
 
158
 
 
159
 
 
160
.. method:: RExec.r_reload(module)
 
161
 
 
162
   Reload the module object *module*, re-parsing and re-initializing it.
 
163
 
 
164
 
 
165
.. method:: RExec.r_unload(module)
 
166
 
 
167
   Unload the module object *module* (remove it from the restricted environment's
 
168
   ``sys.modules`` dictionary).
 
169
 
 
170
And their equivalents with access to restricted standard I/O streams:
 
171
 
 
172
 
 
173
.. method:: RExec.s_import(modulename[, globals[, locals[, fromlist]]])
 
174
 
 
175
   Import the module *modulename*, raising an :exc:`ImportError` exception if the
 
176
   module is considered unsafe.
 
177
 
 
178
 
 
179
.. method:: RExec.s_reload(module)
 
180
 
 
181
   Reload the module object *module*, re-parsing and re-initializing it.
 
182
 
 
183
 
 
184
.. method:: RExec.s_unload(module)
 
185
 
 
186
   Unload the module object *module*.
 
187
 
 
188
   .. XXX what are the semantics of this?
 
189
 
 
190
 
 
191
.. _rexec-extension:
 
192
 
 
193
Defining restricted environments
 
194
--------------------------------
 
195
 
 
196
The :class:`RExec` class has the following class attributes, which are used by
 
197
the :meth:`__init__` method.  Changing them on an existing instance won't have
 
198
any effect; instead, create a subclass of :class:`RExec` and assign them new
 
199
values in the class definition. Instances of the new class will then use those
 
200
new values.  All these attributes are tuples of strings.
 
201
 
 
202
 
 
203
.. attribute:: RExec.nok_builtin_names
 
204
 
 
205
   Contains the names of built-in functions which will *not* be available to
 
206
   programs running in the restricted environment.  The value for :class:`RExec` is
 
207
   ``('open', 'reload', '__import__')``. (This gives the exceptions, because by far
 
208
   the majority of built-in functions are harmless.  A subclass that wants to
 
209
   override this variable should probably start with the value from the base class
 
210
   and concatenate additional forbidden functions --- when new dangerous built-in
 
211
   functions are added to Python, they will also be added to this module.)
 
212
 
 
213
 
 
214
.. attribute:: RExec.ok_builtin_modules
 
215
 
 
216
   Contains the names of built-in modules which can be safely imported. The value
 
217
   for :class:`RExec` is ``('audioop', 'array', 'binascii', 'cmath', 'errno',
 
218
   'imageop', 'marshal', 'math', 'md5', 'operator', 'parser', 'regex', 'select',
 
219
   'sha', '_sre', 'strop', 'struct', 'time')``.  A similar remark about overriding
 
220
   this variable applies --- use the value from the base class as a starting point.
 
221
 
 
222
 
 
223
.. attribute:: RExec.ok_path
 
224
 
 
225
   Contains the directories which will be searched when an :keyword:`import` is
 
226
   performed in the restricted environment.   The value for :class:`RExec` is the
 
227
   same as ``sys.path`` (at the time the module is loaded) for unrestricted code.
 
228
 
 
229
 
 
230
.. attribute:: RExec.ok_posix_names
 
231
 
 
232
   Contains the names of the functions in the :mod:`os` module which will be
 
233
   available to programs running in the restricted environment.  The value for
 
234
   :class:`RExec` is ``('error', 'fstat', 'listdir', 'lstat', 'readlink', 'stat',
 
235
   'times', 'uname', 'getpid', 'getppid', 'getcwd', 'getuid', 'getgid', 'geteuid',
 
236
   'getegid')``.
 
237
 
 
238
   .. Should this be called ok_os_names?
 
239
 
 
240
 
 
241
.. attribute:: RExec.ok_sys_names
 
242
 
 
243
   Contains the names of the functions and variables in the :mod:`sys` module which
 
244
   will be available to programs running in the restricted environment.  The value
 
245
   for :class:`RExec` is ``('ps1', 'ps2', 'copyright', 'version', 'platform',
 
246
   'exit', 'maxint')``.
 
247
 
 
248
 
 
249
.. attribute:: RExec.ok_file_types
 
250
 
 
251
   Contains the file types from which modules are allowed to be loaded. Each file
 
252
   type is an integer constant defined in the :mod:`imp` module. The meaningful
 
253
   values are :const:`PY_SOURCE`, :const:`PY_COMPILED`, and :const:`C_EXTENSION`.
 
254
   The value for :class:`RExec` is ``(C_EXTENSION, PY_SOURCE)``.  Adding
 
255
   :const:`PY_COMPILED` in subclasses is not recommended; an attacker could exit
 
256
   the restricted execution mode by putting a forged byte-compiled file
 
257
   (:file:`.pyc`) anywhere in your file system, for example by writing it to
 
258
   :file:`/tmp` or uploading it to the :file:`/incoming` directory of your public
 
259
   FTP server.
 
260
 
 
261
 
 
262
An example
 
263
----------
 
264
 
 
265
Let us say that we want a slightly more relaxed policy than the standard
 
266
:class:`RExec` class.  For example, if we're willing to allow files in
 
267
:file:`/tmp` to be written, we can subclass the :class:`RExec` class::
 
268
 
 
269
   class TmpWriterRExec(rexec.RExec):
 
270
       def r_open(self, file, mode='r', buf=-1):
 
271
           if mode in ('r', 'rb'):
 
272
               pass
 
273
           elif mode in ('w', 'wb', 'a', 'ab'):
 
274
               # check filename : must begin with /tmp/
 
275
               if file[:5]!='/tmp/': 
 
276
                   raise IOError, "can't write outside /tmp"
 
277
               elif (string.find(file, '/../') >= 0 or
 
278
                    file[:3] == '../' or file[-3:] == '/..'):
 
279
                   raise IOError, "'..' in filename forbidden"
 
280
           else: raise IOError, "Illegal open() mode"
 
281
           return open(file, mode, buf)
 
282
 
 
283
Notice that the above code will occasionally forbid a perfectly valid filename;
 
284
for example, code in the restricted environment won't be able to open a file
 
285
called :file:`/tmp/foo/../bar`.  To fix this, the :meth:`r_open` method would
 
286
have to simplify the filename to :file:`/tmp/bar`, which would require splitting
 
287
apart the filename and performing various operations on it.  In cases where
 
288
security is at stake, it may be preferable to write simple code which is
 
289
sometimes overly restrictive, instead of more general code that is also more
 
290
complex and may harbor a subtle security hole.