@@ -2,4 +2,199 @@ \section{Standard Module \sectcode{rexec}}
22\stmodindex {rexec}
33\renewcommand {\indexsubitem }{(in module rexec)}
44
5- XXX To be provided.
5+ This 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
8+ Python functions \code {exec()}, \code {eval()}, \code {execfile()}, and
9+ \code {import()}. Code executed in this restricted environment will
10+ only have access to modules and functions that are deemed safe; you
11+ can subclass \code {RExec} to add or remove capabilities as desired.
12+
13+ \emph {Note: } The \code {RExec} class can prevent code from performing
14+ unsafe operations like reading or writing disk files, or using TCP/IP
15+ sockets. However, it does not protect against code using extremely
16+ large amounts of memory or CPU time.
17+ % XXX is there any protection against this?
18+
19+ \begin {funcdesc }{RExec}{\optional {hooks\, verbose} }
20+ Returns 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.
25+ Whenever the RExec module searches for a module (even a built-in one)
26+ or reads a module's code, it doesn't actually go out to the file
27+ system itself. Rather, it calls methods of an RHooks instance that
28+ was passed to or created by its constructor. (Actually, the RExec
29+ object doesn't make these calls---they are made by a module loader
30+ object that's part of the RExec object. This allows another level of
31+ flexibility, e.g. using packages.)
32+
33+ By providing an alternate RHooks object, we can control the actual
34+ file system accesses made to import a module, without changing the
35+ actual algorithm that controls the order in which those accesses are
36+ made. For instance, we could substitute an RHooks object that passes
37+ all filesystem requests to a file server elsewhere, via some RPC
38+ mechanism such as ILU. Grail's applet loader uses this to support
39+ importing applets from a URL for a directory.
40+
41+ % XXX does verbose actually do anything at the moment?
42+ If \var {verbose} is true, additional debugging output will be sent to
43+ standard output.
44+ \end {funcdesc }
45+
46+ RExec instances have the following attributes, which are used by the
47+ \code {__init__} method. Changing them on an existing instance won't
48+ have any effect; instead, create a subclass of \code {RExec} and assign
49+ them new values in the class definition. Instances of the new class
50+ will then use those new values. All these attributes are tuples of
51+ strings.
52+
53+ \renewcommand {\indexsubitem }{(RExec object attribute)}
54+ \begin {datadesc }{nok_builtin_names}
55+ Contains 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}
62+ Contains the names of built-in modules which can be safely imported.
63+ The 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}
69+ Contains the directories which will be searched when an \code {import}
70+ is performed in the restricted environment.
71+ The value for \code {RExec} is the same as \code {sys.path} for
72+ unrestricted code.
73+ \end {datadesc }
74+
75+ \begin {datadesc }{ok_posix_names}
76+ % Should this be called ok_os_names?
77+ Contains the names of the functions in the \code {os} module which will be
78+ available to programs running in the restricted environment. The
79+ value 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}
87+ Contains the names of the functions and variables in the \code {sys} module which will be
88+ available to programs running in the restricted environment. The
89+ value for \code {RExec} is \code {('ps1',} \code {'ps2',}
90+ \code {'copyright',} \code {'version',} \code {'platform',} \code {'exit',}
91+ \code {'maxint')}.
92+ \end {datadesc }
93+
94+ RExec 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
99+ be 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,
104+ which will be executed in the restricted environment.
105+ \end {funcdesc }
106+
107+ \begin {funcdesc }{r_execfile}{filename}
108+ Execute the Python code contained in the file \var {filename} in the
109+ restricted environment.
110+ \end {funcdesc }
111+
112+ Methods whose names begin with \code {s_} are similar to the functions
113+ beginning with \code {r_}, but the code will be granted access to
114+ restricted 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
119+ be 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,
124+ which will be executed in the restricted environment.
125+ \end {funcdesc }
126+
127+ \begin {funcdesc }{s_execfile}{code}
128+ Execute the Python code contained in the file \var {filename} in the
129+ restricted environment.
130+ \end {funcdesc }
131+
132+ \code {RExec} objects must also support various methods which will be implicitly called
133+ by code executing in the restricted environment. Overriding these
134+ methods 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}}
137+ Import the module \var {modulename}, raising an \code {ImportError} exception
138+ if the module is considered unsafe.
139+ \end {funcdesc }
140+
141+ \begin {funcdesc }{r_open}{filename\optional {\, mode\optional {\, bufsize}}}
142+ Method called when \code {open()} is called in the restricted
143+ environment. The arguments are identical to those of \code {open()},
144+ and a file object (or a class instance compatible with file objects)
145+ should be returned. \code {RExec}'s default behaviour is allow opening
146+ any file for reading, but forbidding any attempt to write a file. See
147+ the example below for an implementation of a less restrictive \code {r_open()}.
148+ \end {funcdesc }
149+
150+ \begin {funcdesc }{r_reload}{module}
151+ Reload the module object \var {module}, re-parsing and re-initializing it.
152+ \end {funcdesc }
153+
154+ \begin {funcdesc }{r_unload}{module}
155+ Unload 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}}
160+ Import the module \var {modulename}, raising an \code {ImportError} exception
161+ if the module is considered unsafe.
162+ \end {funcdesc }
163+
164+ \begin {funcdesc }{s_reload}{module}
165+ Reload the module object \var {module}, re-parsing and re-initializing it.
166+ \end {funcdesc }
167+
168+ \begin {funcdesc }{s_unload}{module}
169+ Unload the module object \var {module}.
170+ % XXX what are the semantics of this?
171+ \end {funcdesc }
172+
173+ \subsection {An example }
174+
175+ Let us say that we want a slightly more relaxed policy than the
176+ standard 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 }
180+ class 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+
192+ Notice that the above code will occasionally forbid a perfectly valid
193+ filename; for example, code in the restricted environment won't be
194+ able 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
197+ performing various operations on it. In cases where security is at
198+ stake, it may be preferable to write simple code which is sometimes
199+ overly restrictive, instead of more general code that is also more
200+ complex and may harbor a subtle security hole.
0 commit comments